查看以下C代码。
char * str1 = "hello";
它创建一个分配给只读内存的char数组,str1指定为第一个元素的指针。由于只读,如果没有分段错误,则无法更改内存。在这个声明中:
int * p = 1;
p
现在被分配为1,实际上可以重新分配给不同的值而不会发生分段错误。为什么是这样?只是编译器决定只在字符串文字的情况下才能读取内存吗?
答案 0 :(得分:8)
似乎有很多事情你误解了。
首先来到这里:
char * str1 = "hello";
没有人限制你做
str1 = "hello again";
稍后。它仍然是正确的。但是你不能做的是:
str1[0] = 'a'; // This you can't do- because you aren't allowed to modify string literal
所以这意味着你不应该改变字符串文字,但你可以使指针指向另一个对象。
使用整数示例:
int * p = 1;
上面的行不好,因为p
现在指向内存地址1并且取消引用它是一个坏主意。
从功能上讲,char
或int
指针的行为大致相同,只是你无法修改字符串文字,这是唯一的限制。
如果同时使用char
和int
指针,您可以重新指定指针。
并且(除了char指针指向字符串文字的情况),您还可以更改它们指向的对象的内容。 e.g。
int x = 1;
int *y = &x;
*y = 19; // Fine, now x has value 19
char a = 'b';
char *c = &a;
*c = 'r'; // Fine, now a has value 'r'
总结一下,我会这样说:char
和int
指针和所有指针一般“行为”的方式相同:你可以为它们分配地址,也可以更改它们的对象point(授予它们指向有效内存),只是在字符串文字的情况下,如果char
指针碰巧指向字符串文字,则不允许更改 对象<{1}}指针指向的。
答案 1 :(得分:7)
int * p = 1;
p
现在分配为1。
<强>错误。 p
现在指向内存地址1。
这可能会导致各种问题,首先是您没有从该地址开始正确分配任何内存块。
更糟糕的是,即使您以某种方式设法在地址1处分配了一个内存块,因为该地址未与int
对齐(即1不能被{{1}整除}),您的代码容易出现未对齐的加载/存储操作。
如果您的平台(即指定的编译器+底层硬件架构)不支持这些操作,则任何通过sizeof int
读取或写入的尝试都可能导致:
前者比后者更好,因为有了总线故障,至少你会立即意识到这个问题,而对于一个未确定的结果,某些意外的行为可能会在你的程序执行期间的某个后期出现,你受调试之神的怜悯。
答案 2 :(得分:1)
很好的问题,首先要比较一下:
char* str1 = "hello";
const char* const str1 = "hello";
char str1[] = "hello";
char* str1 = "hello";
中的 str1是一个指向char类型的指针。你可以做指针运算,str1++
将编译,这会将数据放入内存的只读部分(const数据)。并使用str1 [0] =&#39; a&#39 ;;将导致运行时错误(但编译好)
在const char* const str1 = "hello";
中,数据和指针是const:使用str1[0]='a';
将导致编译错误
in char str1[] = "hello";
str1是一个数组(const指针)。使用str1[0]='a';
是可以的,但使用str1++
将导致编译错误:
#include <stdio.h>
void reverse(char *p){
char c;
char* q = p;
while (*q) q++;
q--; // point to the end
while (p < q) {
c = *p;
*p++ = *q;
*q-- = c;
}
}
int main(){
char s[] = "DCBA";
reverse( s);
printf("%s\n", s); // ABCD
}
和第二:
关于指针的好处是:指针也是一个变量,比如&#39; int&#39;有一点不同:
使用i++
和int只需将{1}添加到i
,但带有指针的p++
会添加一个基础类型的内存大小,例如int32_t* p;
p ++将p(int32_t大小)加到p值
p++
增加p变量内存本身,而不是它可能指向的内存。(这是你正在寻找的答案)。
现在比较一下:
int ary[] = { 1, 2, 3 };
//int* p2 = { 1, 2, 3 };
int* p = ary;
const int* const q = ary;
在此示例中:
#include <stdio.h>
int main() {
int ary[] = { 1, 2, 3 };
//int* p2 = { 1, 2, 3 };
int* p = ary;
const int* const q = ary;
ary[0] = 10; // ok
p[0] = 100; // ok
//q[0] = 11; // error
printf("%x\n", p);
printf("%d\n", p[0]); // 100
return 0;
}
虽然char* str1 = "hello";
有效,但int* p2 = { 1, 2, 3 };
无效。 char* p2 = { 'h', 'e', 'l', 'l', 'o', 0 };
也无效。所以char* str1 = "hello";
是编译时特殊的编译器技巧,它将&#34; hello&#34;在只读存储空间。
我希望这会有所帮助。