C 带参数的宏

C 带参数的宏,c,pointers,macros,C,Pointers,Macros,在下面的代码中,我不断得到一个错误。如何修改第三行?为什么这种情况一直发生?怎么了 #include <stdio.h> #include "stdlib.h" #define ARRAY_IDX(type, array, i) ((type *)(array+i)) // you can only modify this line! int main(int argc, const char * argv[]) { void *ptr = malloc(10*sizeo

在下面的代码中,我不断得到一个错误。如何修改第三行?为什么这种情况一直发生?怎么了

#include <stdio.h> 
#include "stdlib.h"
#define ARRAY_IDX(type, array, i) ((type *)(array+i)) // you can only modify this line!

int main(int argc, const char * argv[]) {
    void *ptr = malloc(10*sizeof(int));
#ifdef ARRAY_IDX
    for (int i = 0; i < 10; i++) {
        ARRAY_IDX(int, ptr, i) = i * 2;
    }

    for (int i = 0; i < 10; i++) {
        printf("%d ", ARRAY_IDX(int, ptr, i));
    }
    free(ptr);
#else
    printf("Implement ARRAY_IDX first");
#endif
}
#包括
#包括“stdlib.h”
#定义ARRAY_IDX(type,ARRAY,i)((type*)(ARRAY+i))//只能修改此行!
int main(int argc,const char*argv[]{
void*ptr=malloc(10*sizeof(int));
#ifdef数组_IDX
对于(int i=0;i<10;i++){
数组_IDX(int,ptr,i)=i*2;
}
对于(int i=0;i<10;i++){
printf(“%d”,数组_IDX(int,ptr,i));
}
免费(ptr);
#否则
printf(“首先实现数组_IDX”);
#恩迪夫
}

向空指针添加int没有什么错。多年来,编译器设计人员一直认为这是标准行为,并以此实现。它的每一点都和匿名结构和联合一样标准,编译器已经使用了近20年,直到最近才在C11中添加了匿名结构和联合。实际上,所有编译器都可以很好地编译它,没有任何警告或错误,也不必使用任何特殊的编译器标志

正如我指出的,您的问题是,您正在为指针赋值。您需要在演员阵容结束后取消对它的引用

#define ARRAY_IDX(type, array, i) ((type *)array)[i]
看着

ARRAY_IDX(int, ptr, i) = i * 2;

显示表达式

ARRAY_IDX(int, whatever, whatever)
应展开为类型为
int
的表达式(以及左值,以便我们可以为其赋值)

首先从一个
void*
开始,因为您想索引该数组的元素(而不是它的单个字节,这将违反别名),所以需要首先将其设置为
int*

(int *)(ptr)
现在您有了一个指向整数(希望是数组)的指针。增加它:

(int *)(ptr) + (idx)
最后,需要一个左值
int
表达式。取消对指针的引用以获取该值:

(*((int *)(ptr) + (idx)))
将其转换为预处理器宏应该是可行的,所以我将它留给您



请注意,无论是谁给你代码,他都不是你应该信任的老师。这不会教你很多关于正确的C语言的知识,它可能会教你一些关于预处理器的知识。但是不要写这样的代码。别这样。如果可能,请使用正确的类型。检查
malloc

“错误”-->哪个错误失败?()在标准C编译器中,不能像宏尝试做的那样为
void*
编制索引。默认情况下,GCC允许它,但默认情况下,GCC不是标准的C编译器。宏中还缺少一个间接运算符。仍然没有完全定义。您仍在为非标准C的
void*
编制索引,并且没有足够的括号。错误!您已经将
(数组+i)
添加到
void*
,因为代码中的
ptr
(作为宏的
array
参数传递)是
void*
。这是不允许的。@DeftlyHacked你不能在
void*
上做指针算术(没有大小…那么
+1
应该让指针前进多少字节?@DeftlyHacked最好冷静一点。你错了:@DeftlyHacked:如果你在GCC兼容模式下使用GCC或Clang,并且你没有强迫它使用
-std=c11-pedantic
或类似的东西,那么你是对的,GCC确实允许你索引
void*
,并且它或多或少地等同于
char*
。但是,标准C不允许这样做。更糟糕的是,当您使用GCC索引a
void*
时,您将导致访问未对齐-
ptr+1
未正确对齐
int
。它会给你更多未定义的行为。在RISC芯片上,可能会出现总线错误。CISC芯片可能会给你一个结果,但它是错误的。
(*((int *)(ptr) + (idx)))