你是默认启用和allowspointer arithmetics上的指针作废和指针由治疗无效的函数或大小为1。该扩展功能非标准GCC扩展的受害者可以通过使用-std
选项(例如-std=c99
(详情请参见gcc manual page))将C标准指定为C99来禁用。或者,您可以通过指定-Wpointer-arith
选项,让gcc对这些情况发出警告。
回到问题,考虑当你写&data[tmpFrom]
会发生什么。采用data
指向的地址,然后将tmpFrom
字节添加到该地址。你想要的是添加tmpFrom * sizeof(int)
字节。为此,您必须根据tmpFrom
的值和int
类型的值手动计算所需的字节数,或者将data
指针声明为指向int
类型的指针。第二个是首选的方法,但如果你真的希望你的函数支持任意数据类型,那么你必须回到更困难的第一种方法。
下面是铛产生警告的列表(通常好了很多与诊断):
$ clang -Wall -pedantic -o test ./test.c
./test.c:109:18: warning: subscript of a pointer to void is a GNU extension [-pedantic,-Wpointer-arith]
memcpy(a, &data[tmpFrom], szblob);
~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~
/usr/include/secure/_string.h:55:36: note: expanded from macro 'memcpy'
? __builtin___memcpy_chk (dest, src, len, __darwin_obsz0 (dest)) \
^
./test.c:109:13: warning: ISO C forbids taking the address of an expression of type 'void' [-pedantic]
memcpy(a, &data[tmpFrom], szblob);
~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~
/usr/include/secure/_string.h:55:36: note: expanded from macro 'memcpy'
? __builtin___memcpy_chk (dest, src, len, __darwin_obsz0 (dest)) \
^
./test.c:109:18: warning: subscript of a pointer to void is a GNU extension [-pedantic,-Wpointer-arith]
memcpy(a, &data[tmpFrom], szblob);
~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~
/usr/include/secure/_string.h:56:33: note: expanded from macro 'memcpy'
: __inline_memcpy_chk (dest, src, len))
^
./test.c:109:13: warning: ISO C forbids taking the address of an expression of type 'void' [-pedantic]
memcpy(a, &data[tmpFrom], szblob);
~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~
/usr/include/secure/_string.h:56:33: note: expanded from macro 'memcpy'
: __inline_memcpy_chk (dest, src, len))
^
./test.c:111:15: warning: subscript of a pointer to void is a GNU extension [-pedantic,-Wpointer-arith]
memcpy(&data[tmpFrom], &data[tmpTo], szblob);
~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/secure/_string.h:54:21: note: expanded from macro 'memcpy'
((__darwin_obsz0 (dest) != (size_t) -1) \
^
/usr/include/secure/_common.h:38:55: note: expanded from macro '__darwin_obsz0'
#define __darwin_obsz0(object) __builtin_object_size (object, 0)
^~~~~~
./test.c:111:10: warning: ISO C forbids taking the address of an expression of type 'void' [-pedantic]
memcpy(&data[tmpFrom], &data[tmpTo], szblob);
~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/secure/_string.h:54:21: note: expanded from macro 'memcpy'
((__darwin_obsz0 (dest) != (size_t) -1) \
^
/usr/include/secure/_common.h:38:55: note: expanded from macro '__darwin_obsz0'
#define __darwin_obsz0(object) __builtin_object_size (object, 0)
^~~~~~
./test.c:111:15: warning: subscript of a pointer to void is a GNU extension [-pedantic,-Wpointer-arith]
memcpy(&data[tmpFrom], &data[tmpTo], szblob);
~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/secure/_string.h:55:30: note: expanded from macro 'memcpy'
? __builtin___memcpy_chk (dest, src, len, __darwin_obsz0 (dest)) \
^
./test.c:111:10: warning: ISO C forbids taking the address of an expression of type 'void' [-pedantic]
memcpy(&data[tmpFrom], &data[tmpTo], szblob);
~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/secure/_string.h:55:30: note: expanded from macro 'memcpy'
? __builtin___memcpy_chk (dest, src, len, __darwin_obsz0 (dest)) \
^
./test.c:111:31: warning: subscript of a pointer to void is a GNU extension [-pedantic,-Wpointer-arith]
memcpy(&data[tmpFrom], &data[tmpTo], szblob);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~
/usr/include/secure/_string.h:55:36: note: expanded from macro 'memcpy'
? __builtin___memcpy_chk (dest, src, len, __darwin_obsz0 (dest)) \
^
./test.c:111:26: warning: ISO C forbids taking the address of an expression of type 'void' [-pedantic]
memcpy(&data[tmpFrom], &data[tmpTo], szblob);
~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~
/usr/include/secure/_string.h:55:36: note: expanded from macro 'memcpy'
? __builtin___memcpy_chk (dest, src, len, __darwin_obsz0 (dest)) \
^
./test.c:111:15: warning: subscript of a pointer to void is a GNU extension [-pedantic,-Wpointer-arith]
memcpy(&data[tmpFrom], &data[tmpTo], szblob);
~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/secure/_string.h:55:62: note: expanded from macro 'memcpy'
? __builtin___memcpy_chk (dest, src, len, __darwin_obsz0 (dest)) \
^
/usr/include/secure/_common.h:38:55: note: expanded from macro '__darwin_obsz0'
#define __darwin_obsz0(object) __builtin_object_size (object, 0)
^~~~~~
./test.c:111:10: warning: ISO C forbids taking the address of an expression of type 'void' [-pedantic]
memcpy(&data[tmpFrom], &data[tmpTo], szblob);
~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/secure/_string.h:55:62: note: expanded from macro 'memcpy'
? __builtin___memcpy_chk (dest, src, len, __darwin_obsz0 (dest)) \
^
/usr/include/secure/_common.h:38:55: note: expanded from macro '__darwin_obsz0'
#define __darwin_obsz0(object) __builtin_object_size (object, 0)
^~~~~~
./test.c:111:15: warning: subscript of a pointer to void is a GNU extension [-pedantic,-Wpointer-arith]
memcpy(&data[tmpFrom], &data[tmpTo], szblob);
~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/secure/_string.h:56:27: note: expanded from macro 'memcpy'
: __inline_memcpy_chk (dest, src, len))
^
./test.c:111:10: warning: ISO C forbids taking the address of an expression of type 'void' [-pedantic]
memcpy(&data[tmpFrom], &data[tmpTo], szblob);
~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/secure/_string.h:56:27: note: expanded from macro 'memcpy'
: __inline_memcpy_chk (dest, src, len))
^
./test.c:111:31: warning: subscript of a pointer to void is a GNU extension [-pedantic,-Wpointer-arith]
memcpy(&data[tmpFrom], &data[tmpTo], szblob);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~
/usr/include/secure/_string.h:56:33: note: expanded from macro 'memcpy'
: __inline_memcpy_chk (dest, src, len))
^
./test.c:111:26: warning: ISO C forbids taking the address of an expression of type 'void' [-pedantic]
memcpy(&data[tmpFrom], &data[tmpTo], szblob);
~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~
/usr/include/secure/_string.h:56:33: note: expanded from macro 'memcpy'
: __inline_memcpy_chk (dest, src, len))
^
./test.c:113:15: warning: subscript of a pointer to void is a GNU extension [-pedantic,-Wpointer-arith]
memcpy(&data[tmpTo], a, szblob);
~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~
/usr/include/secure/_string.h:54:21: note: expanded from macro 'memcpy'
((__darwin_obsz0 (dest) != (size_t) -1) \
^
/usr/include/secure/_common.h:38:55: note: expanded from macro '__darwin_obsz0'
#define __darwin_obsz0(object) __builtin_object_size (object, 0)
^~~~~~
./test.c:113:10: warning: ISO C forbids taking the address of an expression of type 'void' [-pedantic]
memcpy(&data[tmpTo], a, szblob);
~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/secure/_string.h:54:21: note: expanded from macro 'memcpy'
((__darwin_obsz0 (dest) != (size_t) -1) \
^
/usr/include/secure/_common.h:38:55: note: expanded from macro '__darwin_obsz0'
#define __darwin_obsz0(object) __builtin_object_size (object, 0)
^~~~~~
./test.c:113:15: warning: subscript of a pointer to void is a GNU extension [-pedantic,-Wpointer-arith]
memcpy(&data[tmpTo], a, szblob);
~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~
/usr/include/secure/_string.h:55:30: note: expanded from macro 'memcpy'
? __builtin___memcpy_chk (dest, src, len, __darwin_obsz0 (dest)) \
^
./test.c:113:10: warning: ISO C forbids taking the address of an expression of type 'void' [-pedantic]
memcpy(&data[tmpTo], a, szblob);
~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/secure/_string.h:55:30: note: expanded from macro 'memcpy'
? __builtin___memcpy_chk (dest, src, len, __darwin_obsz0 (dest)) \
^
./test.c:113:15: warning: subscript of a pointer to void is a GNU extension [-pedantic,-Wpointer-arith]
memcpy(&data[tmpTo], a, szblob);
~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~
/usr/include/secure/_string.h:55:62: note: expanded from macro 'memcpy'
? __builtin___memcpy_chk (dest, src, len, __darwin_obsz0 (dest)) \
^
/usr/include/secure/_common.h:38:55: note: expanded from macro '__darwin_obsz0'
#define __darwin_obsz0(object) __builtin_object_size (object, 0)
^~~~~~
./test.c:113:10: warning: ISO C forbids taking the address of an expression of type 'void' [-pedantic]
memcpy(&data[tmpTo], a, szblob);
~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/secure/_string.h:55:62: note: expanded from macro 'memcpy'
? __builtin___memcpy_chk (dest, src, len, __darwin_obsz0 (dest)) \
^
/usr/include/secure/_common.h:38:55: note: expanded from macro '__darwin_obsz0'
#define __darwin_obsz0(object) __builtin_object_size (object, 0)
^~~~~~
./test.c:113:15: warning: subscript of a pointer to void is a GNU extension [-pedantic,-Wpointer-arith]
memcpy(&data[tmpTo], a, szblob);
~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~
/usr/include/secure/_string.h:56:27: note: expanded from macro 'memcpy'
: __inline_memcpy_chk (dest, src, len))
^
./test.c:113:10: warning: ISO C forbids taking the address of an expression of type 'void' [-pedantic]
memcpy(&data[tmpTo], a, szblob);
~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/secure/_string.h:56:27: note: expanded from macro 'memcpy'
: __inline_memcpy_chk (dest, src, len))
^
24 warnings generated.
一旦上述警告是固定的,它应该有工作。但是,还有两个问题...
第一个问题是不正确的预期结果。它应该是3, -1, 1, 2
而不是3, -1, 2, 1
。该映射将被排序是这样的:
0,3
1,0
2,1
3,2
而且排列应分四步进行:
1) 2, 3, -1, 1
2) 3, 2, -1, 1
3) 3, -1, 2, 1
4) 3, -1, 1, 2
第二个问题是不正确排序。通过执行两种排序,首先对“from”值和第二个“to”值进行排序,最终得到一个仅由“to”排序的映射(您调用的最后一个排序)。我们应该做的是使用谓词来比较每个元素的“from”和“to”。例如:
int map_comparator(const void *a, const void *b)
{
const MapEntry *s1 = a;
const MapEntry *s2 = b;
if (*s2->indexFrom != *s1->indexFrom) {
return *s1->indexFrom - *s2->indexFrom;
} else {
return *s1->indexTo - *s2->indexTo;
}
}
一旦上述问题得到解决,一切都会奏效。除此之外,您的代码中只有几条建议可能会有所帮助:
- 您正在使用太多的动态分配方式。考虑重新思考你是如何做到的。例如,我看不到需要有
indexFrom
和indexTo
字段的MapEntry
结构动态分配。
- 您有不必要的剧照到
void *
。例如:void * a = (void *)malloc(szblob);
应该只是void *a = malloc(szblob);
。
- 不需要从
void *
转换为其他指针类型,如int *
。这在C中没有必要,其中void *
指针可以隐式转换为其他类型的指针。但是,这不适用于C++。
- 不要
typedef
结构,除非目标是创建一个不透明类型(这不是你的情况)。键入struct
可能看起来像很多输入,但它对于那些阅读您的代码的C开发人员来说是一个很好的提示。例如,请参阅Linux Kernel Coding Style的第5章以获得很好的解释。
我鼓励你自己解决您的代码,但这里是你的代码以最小的必要的修改,使其工作,供大家参考:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#define MAP_SIZE 4
typedef struct MapEntry {
int * indexFrom;
int * indexTo;
} MapEntry;
typedef MapEntry * Map;
int permute(void *data, int nblobs, int szblob, const Map map);
void build_map(Map);
void build_data(int *);
int is_map_valid(Map);
void print_map(Map);
int is_valid(Map);
int map_comparator(const void * a, const void * b);
int main(int argc, char const *argv[])
{
int nblobs, * data, i;
size_t szblob;
Map map = (Map)malloc(sizeof(Map));
data = (int *) malloc(sizeof(int) * 4);
build_map(map);
data[0] = 1;
data[1] = 3;
data[2] = -1;
data[3] = 2;
nblobs = 4;
szblob = sizeof(int);
if (!permute(data, nblobs, szblob, map)) {
printf("Invalid Map\n");
return 0;
}
i = 0;
for (i = 0; i < szblob; ++i) {
printf("%d ", data[i]);
}
return 0;
}
void print_map(Map map){
int i;
for (i = 0; i < MAP_SIZE; ++i) {
printf("[%d - %d]\n", *map[i].indexFrom, *map[i].indexTo);
}
}
int map_comparator(const void *a, const void *b)
{
const MapEntry *s1 = a;
const MapEntry *s2 = b;
if (*s2->indexFrom != *s1->indexFrom) {
return *s1->indexFrom - *s2->indexFrom;
} else {
return *s1->indexTo - *s2->indexTo;
}
}
int is_map_valid(Map map) {
int i,j;
for (i = 1; i < MAP_SIZE; ++i){
j = i - 1;
if (*map[j].indexFrom == *map[i].indexFrom)
return 0;
if (*map[j].indexTo == *map[i].indexTo)
return 0;
}
return 1;
}
int is_valid(Map map) {
qsort(map, MAP_SIZE, sizeof(MapEntry), map_comparator);
if (!is_map_valid(map)) return 0;
return 1;
}
int permute(void *data, int nblobs, int szblob, const Map map){
int i, tmpFrom, tmpTo;
void * a = (void *)malloc(szblob);
char *p = data;
/* check if map has duplicate keys */
/* sort the list, then check whether or not the map is valid */
if (!is_valid(map)) return 0;
/* where issues occur */
for (i = 0; i < nblobs; ++i){
tmpFrom = *map[i].indexFrom;
tmpTo = *map[i].indexTo;
memcpy(a, &p[tmpFrom*szblob], szblob);
memcpy(&p[tmpFrom*szblob], &p[tmpTo*szblob], szblob);
memcpy(&p[tmpTo*szblob], a, szblob);
}
return 1;
}
/* build mapping */
void build_map(Map map){
int i;
for (i = 0; i < MAP_SIZE; ++i) {
map[i].indexFrom = (int *)malloc(sizeof(int));
map[i].indexTo = (int *)malloc(sizeof(int));
}
*map[0].indexFrom = 0;
*map[0].indexTo = 3;
*map[1].indexFrom = 3;
*map[1].indexTo = 2;
*map[2].indexFrom = 2;
*map[2].indexTo = 1;
*map[3].indexFrom = 1;
*map[3].indexTo = 0;
}
希望它能帮助。保持温暖,祝你好运!
为什么MapEntry中的索引是“int *”而不是普通的“int”?特别是在64位机器上,在结构中使用动态分配的指针而不是简单的'int'会浪费内存的_lot_(如果MapEntry是动态分配的,则使用类似48字节的动态分配开销而不是16个字节)或8 if不是这样)。 –
我不知道这一点。代码现在应该反映固定的结构。首先是 –