c/c++语言开发共享为什么将derefernce指针设置为等于原始非法?

为什么设置解除引用指针的值会引发分段错误11? 为了明确我的意思,请查看以下代码:

#include  int *ptr; *ptr = 2; int main(){ printf("%dn", *ptr); return 0; } 

我认为* ptr = 2会将指针ptr指向的rvalue设置为2.是不是这样? 对于那些c专家程序员,我很抱歉,这真的很容易/很明显。

如果该值具有内存地址,我们是否只允许将取消引用的指针(即* ptr)设置为值? 即喜欢做:

 int k = 7; int *ptr = k; 

然后:

 *ptr = 2; 

    这里的问题是ptr没有指向分配的空间。 请参阅以下内容:

     #include  #include  int main(void){ // Create a pointer to an integer. // This pointer will point to some random (likely unallocated) memory address. // Trying set the value at this memory address will almost certainly cause a segfault. int *ptr; // Create a new integer on the heap, and assign its address to ptr. // Don't forget to call free() on it later! ptr = malloc(sizeof(*ptr)); // Alternatively, we could create a new integer on the stack, and have // ptr point to this. int value; ptr = &value; // Set the value of our new integer to 2. *ptr = 2; // Print out the value at our now properly set integer. printf("%dn", *ptr); return 0; } 

    它不是“非法的”,只是简单的实现定义。 实际上,在某些平台(例如DOS)上,需要特定的内存地址,例如将文本写入以0xB8000开头的video缓冲区,或者将内存映射到SNES上的控制器I / O.

    在大多数当前的操作系统中,出于安全原因使用了一个名为ASLR的function,这使得专用地址的古老模式成为过去,有利于通过驱动程序和内核层,这使得它对大多数地方来说是“非法的”你会运行它。

    这里最基本的问题是你没有将ptr分配给有效的内存地址,在某些情况下, 0是有效的内存地址,但通常不是。 由于ptr在第一种情况下是全局变量 ,因此它将初始化为0 。 雷米巴尔问了一个很好的后续问题, 最好的回答让我意识到这是一个重新宣布:

     *ptr = 2; 

    然后你将ptr设置为值为2 ,除非偶然指向有效的内存地址。

    如果ptr是一个本地或自动变量,那么它将是未初始化的,它的值将是不确定的。 在C和C ++中使用具有不确定值的指针是未定义的行为 。 虽然允许实现定义行为,但在大多数情况下使用NULL指针也是未定义的行为。

    在大多数试图访问内存的现代系统中,您的进程不拥有将导致分段错误 。

    您可以通过几种方式为ptr分配有效的内存地址,例如:

     int k = 7; int *ptr = &k; ^ 

    注意使用of来获取k的地址,或者你可以使用malloc为它动态分配内存。

    您的代码无效,但某些C编译器可能允许它与旧版本的语言兼容。

    如果语句出现在函数体外,则语句(包括赋值语句)是非法的(语法错误)。

    你有:

     int *ptr; *ptr = 2; 

    在文件范围。 第一行是一个名为ptrint*对象的有效声明,隐式初始化为空指针值。 第二行看起来像赋值语句,但由于它在函数外部,编译器很可能甚至不会尝试以这种方式解释它。 gcc将其视为声明 。 旧版本的C允许您在声明中省略类型名称; C99删除了“隐含int ”规则。 所以gcc对待

     *ptr = 2; 

    相当于

     int *ptr = 2; 

    并产生以下警告:

     cc:4:1: warning: data definition has no type or storage class [enabled by default] cc:4:8: warning: initialization makes pointer from integer without a cast [enabled by default] 

    第一个警告是因为您从声明中省略了int (或其他类型名称)。 第二个是因为2int类型的值,并且您正在使用它来初始化int*类型的对象; 没有从intint*隐式转换(除了空指针常量的特殊情况)。

    一旦你越过它,你有两个相同对象的声明 – 但它们是兼容的,所以这是允许的。 并且指针变量被初始化为(int*)2 ,这是一个垃圾指针值(在内存地址0x00000002可能没有任何用处)。

    在您的mainfunction中,您可以:

     printf("%dn", *ptr); 

    它试图在该内存地址处打印int对象的值。 由于该地址不太可能是您的程序有权访问的地址,因此分段错误并不是一个令人惊讶的结果。 (更一般地说,行为未定义。)

    (这在C中是一个相当普遍的问题:程序中的小错误可能会导致某些内容仍然编译,但与您的意图完全不同。我想到的方式是C的语法相对“密集”;小随机调整到有效的程序通常会生成不同但语法上有效的程序,而不是创建语法错误。)

    这就是你的程序实际上做的事情; 我确定这不是你打算做的。

    深呼吸,继续阅读。


    这里的东西可能更接近你的意图:

     #include  int *ptr; int main(void) { *ptr = 2; printf("%dn", *ptr); return 0; } 

    由于现在没有ptr的初始化器,因此它被隐式初始化为空指针值。 (如果在main中定义了ptr ,它的初始值将是垃圾。)赋值语句尝试取消引用该空指针,导致分段错误(同样,行为未定义;分段错误可能是结果)。 执行永远不会到达printf调用。

    我认为*ptr=2会将指针ptr指向的rvalue设置为2.是不是这样?

    不完全的。 指针不指向右值; “rvalue”仅仅是表达式的价值。 指针指向对象 (如果它们指向任何东西)。 分配

     *ptr = 2; 

    2赋给ptr指向的对象 – 但是ptr不指向对象!

    现在让我们看一下你的程序实际可行的版本:

     #include  int *ptr; int variable; int main(void) { ptr = &variable; *ptr = 2; printf("*ptr = %dn", *ptr); printf("variable = %dn", variable); return 0; } 

    现在ptr指向一个对象, *ptr = 2为该对象赋值。 输出是:

     *ptr = 2 variable = 2 

      以上就是c/c++开发分享为什么将derefernce指针设置为等于原始非法?相关内容,想了解更多C/C++开发(异常处理)及C/C++游戏开发关注计算机技术网(www.ctvol.com)!)。

      本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。

      ctvol管理联系方式QQ:251552304

      本文章地址:https://www.ctvol.com/c-cdevelopment/549494.html

      (0)
      上一篇 2021年1月14日
      下一篇 2021年1月14日

      精彩推荐