'char*`和'int'之间的语义不同*`
我想知道为什么在C中声明和分配'char*`和'int'之间的语义不同*`,c,pointers,C,Pointers,我想知道为什么在C中声明和分配char*与int*具有不同的语义 以下所有代码都是使用标志-Wall-Werror-std=gnu99--pedantic用clang编译的。 我正在试图了解这种差异是否是真实存在的,或者在int*和char*之间是否存在更大的差异,我还没有意识到这一点 //这将编译 int main(int argc,const char*argv[]{ char*a; a=“1”; printf(“a:%s\n”,a); 返回退出成功; } //这将不会编译。这是一个并行结
char*
与int*
具有不同的语义
以下所有代码都是使用标志-Wall-Werror-std=gnu99--pedantic
用clang
编译的。
我正在试图了解这种差异是否是真实存在的,或者在int*
和char*
之间是否存在更大的差异,我还没有意识到这一点
//这将编译
int main(int argc,const char*argv[]{
char*a;
a=“1”;
printf(“a:%s\n”,a);
返回退出成功;
}
//这将不会编译。这是一个并行结构,用char代替int
#包括
#包括
int main(int argc,const char*argv[]{
int*a;
a=1;
printf(“a:%d\n”,a);
返回退出成功;
}
//但这将编译
#包括
#包括
int main(int argc,const char*argv[]{
int*a;
int b=1;
a=&b;
printf(“a:%d\n”,*a);
返回退出成功;
}
其要点:
“1”
的数据类型是char*
。因此,您将char*
赋值给char*
变量
1
的数据类型为int
。因此,您正在将int
赋值给int*
变量,该变量由于类型不匹配而无法工作。第二个示例无法编译,因为您启用了-Werror,并且您正试图将整数赋值给一个没有强制转换的指针,这通常只是一个警告。如果你做了char*a;a='a'代码>因为您将尝试为char*分配一个char
指针类型之间的语义不同——内存中作为指针存储的内容可能不会不同,但指针类型会影响编译。主要涉及指针算法、数组索引和使用指针聚合(结构)类型和函数
当您开始使用指针算术/数组索引时,情况就不同了。例如:
int value = 4
char *charp = &value;
int* intp = &value;
这两个都是有效的指针。如果使用函数指针(可以使用函数调用语法)和结构指针(可以使用->
运算符访问引用结构的成员),则在编译过程中还将看到不同的行为。处理数组、指针和标量语义之间的差异
除非它是sizeof
或一元&
运算符的操作数,或者是用于初始化声明中字符数组的字符串文字,否则“T
的N元素数组”类型的表达式将被转换(“衰减”)为“指向T
的指针”类型的表达式,表达式的值将是数组第一个元素的地址
字符串literal“1”
是类型为char[2]
的数组表达式。在此上下文中,它“衰减”为char*
类型的表达式,表达式的值是字符串第一个字符的地址。因此,您正在分配“喜欢”到“喜欢”:
a = "l"; // char * = char *
整数变量不会发生这种情况。文本1
具有类型int
,但您正试图将该int
值分配给int*
对象:
a = 1; // int * = int
这将触发诊断。只能将int*
值分配给int*
对象-需要显式强制转换1
:
a = (int *) 1;
这将抑制诊断,但
1
很可能不是您平台上的有效内存地址,尝试使用它将导致问题 区别不是在char*
和int*
之间,而是在“1”
和1
之间;a=“1”将a
设置为字符串literal“1”
的地址。我马上想到的主要区别是指针算法和数组索引((char*)a)[5]
与((int*)a)[5]
的位置不同,因此区别在于字符串文字“1”本身是一个引用,而整数文字1是一个值。可能有更确切的方式来表达这个短语。为了完整性,也要考虑<代码>‘a’/COD>一个字符,它像你的int,<代码> char s[] =“hello”<代码>一个数组中的字符串,<代码> int a[] = {1,2,3,4} < /代码>,这两个指针的指针都是相同的,而你的例子是好的,对于新手来说,这也有点像一个陷阱。为什么?因为它只在这个星座是合法的;如果您有char值=4代码>您将违反第三行的严格别名规则。也许你想在这方面扩大你的答案。