当前位置: 首页 > 面试题库 >

Linux上使用C的Char数组和指针进行分段错误

何向荣
2023-03-14
问题内容

所以我有以下程序:

int main(){
  char* one = "computer";
  char two[] = "another";
  two[1]='b';
  one[1]='b';
  return 0;
}

它在“ one [1] =’b’”行上进行段错误,这是有道理的,因为指针“ one”指向的内存必须位于只读内存中。但是,问题是,为什么“ two [1]
=’b’” segfault行没有出现?查看gcc的程序集输出:

.file   "one.c"
        .section        .rodata
.LC0:
        .string "computer"
.LC1:
        .string "another"
        .text
.globl main
        .type   main, @function
main:

我们看到两个字符串都在rodata部分中,因此它们是只读的。那么,为什么“ two [1] =’b’行不存在段错误”呢?


问题答案:

one直接指向位于只读页面中的字符串。另一方面,two是在堆栈上分配的数组,并使用一些常量数据进行初始化。在运行时,可执行文件的只读部分中的字符串将被复制到堆栈中。您要修改的是该字符串在堆栈上的副本,而不是只读存储器页面。

语言的角度来看,在更高层次上"abcd"是type const char*而不是的表达char*。因此,修改此类表达式所指向的值会导致未定义的行为。该语句char* one = "something";仅将指向字符串的指针存储在变量中(不安全,因为它正在抛弃const修饰符)。的char two[] = "something";是完全不同的。它实际上是在声明一个数组并对其进行初始化,就像int a[] = {1,2,3};。引号中的字符串是初始化表达式。



 类似资料:
  • 我解决了一个黑客等级的问题。 编辑 感谢@John的回答。下面是没有seg故障的情况:

  • C++ 指针 在我们讲解指针数组的概念之前,先让我们来看一个实例,它用到了一个由 3 个整数组成的数组:#include <iostream> using namespace std; const int MAX = 3; int main () { int var[MAX] = {10, 100, 200}; for (int i = 0; i < MAX; i++) { cout << "Va

  • C++ 数组 您可以先跳过本章,等了解了 C++ 指针的概念之后,再来学习本章的内容。 如果您对 C++ 指针的概念有所了解,那么就可以开始本章的学习。数组名是一个指向数组中第一个元素的常量指针。因此,在下面的声明中: double balance[50]; balance 是一个指向 &balance[0] 的指针,即数组 balance 的第一个元素的地址。因此,下面的程序片段把 p 赋值

  • 本文向大家介绍在C中使用指针算法的数组总和,包括了在C中使用指针算法的数组总和的使用技巧和注意事项,需要的朋友参考一下 在此程序中,我们需要使用指针算法来查找数组元素的总和。 在这里,我们使用*表示存储在内存地址中的值,并且该地址将保留存储在变量中。因此,“ int * ptr”表示ptr是包含地址的变量,并且地址的内容是整数。 * p表示它是一个指针变量。使用此方法,我们将找出数组元素的总和。

  • C 17(expr.add/4)表示: 当将具有整型的表达式加到指针或从指针中减去时,结果为指针操作数的类型。如果表达式P指向具有n个元素的数组对象x的元素x[i],如果为0,则表达式P J和J P(其中J的值为J)指向(可能是假设的)元素x[i J]≤i j(i j)≤n否则,行为是未定义的。同样,表达式P-J指向(可能是假设的)元素x[i−j] 如果为0≤我−j≤n否则,行为是未定义的。 线标

  • C++ 指针 指针和数组是密切相关的。事实上,指针和数组在很多情况下是可以互换的。例如,一个指向数组开头的指针,可以通过使用指针的算术运算或数组索引来访问数组。请看下面的程序:#include <iostream> using namespace std; const int MAX = 3; int main () { int var[MAX] = {10, 100, 200}; int *pt