int * vs char *初始化

时间:2016-06-26 04:32:54

标签: c

查看以下C代码。

char * str1 = "hello";

它创建一个分配给只读内存的char数组,str1指定为第一个元素的指针。由于只读,如果没有分段错误,则无法更改内存。在这个声明中:

int * p = 1;

p现在被分配为1,实际上可以重新分配给不同的值而不会发生分段错误。为什么是这样?只是编译器决定只在字符串文字的情况下才能读取内存吗?

3 个答案:

答案 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并且取消引用它是一个坏主意。

从功能上讲,charint指针的行为大致相同,只是你无法修改字符串文字,这是唯一的限制。

如果同时使用charint指针,您可以重新指定指针。

并且(除了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'

总结一下,我会这样说:charint指针和所有指针一般“行为”的方式相同:你可以为它们分配地址,也可以更改它们的对象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;在只读存储空间。
我希望这会有所帮助。