3

我是 C 新手,我有这个问题。为什么以下代码会崩溃:

int *a = 10;
*a = 100;
4

10 回答 10

20

因为您正在尝试将 100 写入内存位置 0x0000000A,这可能未分配给您的程序。那是,

int *a = 10;

并不意味着指针'a'将指向内存中值为10的位置。这意味着它指向内存中的地址10(0x0000000A)。然后,您想在该地址中写入一些内容,但您没有这样做的“权利”,因为它没有被分配

您可以尝试以下方法:

int *a = malloc(sizeof(int));
*a = 100;

这会奏效,尽管效率极低。如果您只需要一个 int,则应该将其放入堆栈,而不是堆。在 32 位架构上,指针的长度为 32 位,而 int 的长度也为 32 位,因此指向 int 的指针结构占用(至少)8 个字节的内存空间,而不是 4 个。我们甚至还没有提到缓存问题。

于 2008-10-16T08:46:36.700 回答
12

您需要将指针分配给内存位置,而不是任意值 (10)。

int cell = 10;
int *a = &cell; // a points to address of cell
*a = 100;       // content of cell changed

请参阅对另一个问题的回答,关于小心C

于 2008-10-16T08:45:38.107 回答
7

对于建议使用它为 int 分配内存的所有答案,我想建议对 malloc() 的使用稍作改变。代替:

a = malloc(sizeof(int));

我建议不要重复变量的类型,因为编译器知道这一点并手动重复它会使代码更加密集,并引入错误风险。如果您稍后将声明更改为例如

long *a;

如果不更改分配,您最终会分配错误的内存量(在一般情况下,在 32 位机器上int并且long通常大小相同)。国际海事组织,最好使用:

a = malloc(sizeof *a);

这只是表示“a 指向的类型的大小”,在这种情况下int,这当然是完全正确的。如果像上面那样改变声明中的类型,这一行仍然是正确的。如果您更改赋值左侧的变量名称,仍然存在风险,但至少您不再不必要地重复信息。

另请注意,sizeof在实际对象(即变量)上使用它时不需要括号,只需要类型名称,它看起来像强制转换表达式。sizeof不是函数,而是运算符。

于 2008-10-16T09:00:52.163 回答
2

因为你从来没有为 a 分配任何内存。您刚刚为指向 a 的指针分配了一些堆栈空间。

int *a = NULL;

a = malloc (sizeof (int));

如果(一个!= NULL)
{
*a =10;
}

将工作。

或者,您可以提供一些现有变量的地址,这也可以。

IE

int a* = NULL;
诠释 b = 10;

a = &b;

这现在意味着做类似的事情

*a = 100;

还将 b 设置为 == 100

看看这个: http ://home.netcom.com/~tjensen/ptr/pointers.pdf

于 2008-10-16T08:45:49.433 回答
2

下一行,

int *a = 10;

定义一个指向整数a的指针。然后将指针 a指向内存位置 10。

下一行,

*a = 100;

将值 100 放入 a 指向的内存位置。

问题是:

  1. 你不知道 a 指向哪里。(你不知道内存位置 10 的值)
  2. 无论 a 指向何处,您都可能无权更改该值。它可能是其他一些程序/进程的内存。你这个贼!
于 2008-10-16T08:46:33.753 回答
1

因为您声明了一个指向 int 的指针,所以将指针初始化为 10(一个地址),然后尝试为该地址处的一个 int 赋值。由于地址 10 的内存不属于您的进程,因此您会崩溃。这应该有效:

int *a;
a = malloc(sizeof(int));
*a = 10;
printf("a=%i\n", *a);
free(a);
于 2008-10-16T08:45:49.933 回答
1

这段代码甚至可以编译吗?10 不能转换为int *,除非你像这样转换它:

int *a = (int *) 10;
*a = 100;

在这种情况下,您尝试将 100 写入 10 处的内存地址。这通常不是有效的内存地址,因此您的程序会崩溃。

于 2008-10-16T08:46:00.820 回答
0

它可能会崩溃,因为您将指针分配给您无权访问的内存部分,然后您为该内存位置分配了一些值(不允许这样做!)。

于 2008-10-16T08:46:52.253 回答
0

好的,今天试图给出最简单的解释,同时试图给你更详细的图片。让我们添加一些括号好吗?

(int*) a = 10;
(*a) = 100;

您尝试将四个字节写入地址范围 [10-13]。您的程序的内存布局通常开始较高,因此您的应用程序不会意外覆盖它可以并且仍然起作用的任何内容(例如,来自 .data、.bss 和堆栈)。所以它最终会崩溃,因为地址范围尚未分配。

指针指向内存位置,C 静态类型定义指针的类型。尽管您可以轻松地覆盖指针。简单地:

(void*) v = NULL;

在这里,我们更进一步。什么是空指针?它只是指向地址 0 的指针。

您还可以为指针提供结构类型:

struct Hello {
    int id;
    char* name;
};

...

struct Hello* hello_ptr = malloc(sizeof Hello);
hello_ptr->id = 5;
hello_ptr->name = "Cheery";

好的,什么是malloc?Malloc 分配内存并返回一个指向已分配内存的指针。它具有以下类型签名:

void* malloc(size_t size);

如果您没有保守的垃圾收集器,您的内存很可能最终不会被自动释放。因此,如果您想从刚刚分配的内存中恢复使用,您必须执行以下操作:

free(hello_ptr);

您所做的每个 malloc 中都有一个大小标签,因此您无需说明您为 free 例程指向的块的大小。

好的,还有一件事,字符串在内存中是什么样子的?例如,类似于“Cheery”的那个。简单的回答。它是一个以零结尾的字节数组。

0.1.2.3.4.5. 6
C h e e r y \0
于 2008-10-16T09:23:14.083 回答
0

你也可以这样写:

int* a = 10;
*a = 100;

注意第一行的不同间距。这不是流行的风格,但我个人认为它更清晰。它对编译器具有完全相同的含义。

然后,大声朗读:

"Pointer-to-int 'a' becomes 10"
"Value-pointed-to-by 'a' becomes 100"

代入实际值:

"Value-pointed-to-by 10 becomes 100"

...您意识到 10 不太可能指向您可以使用的一块内存。

您几乎永远不会分配给带有文字的指针:

int* ptr = (int*)10;  // You've guessed at a memory address, and probably got it wrong
int* ptr = malloc(sizeof(int)); // OS gives you a memory address at runtime  

我想可能有一些非常低级的工作,您可以直接指定绝对内存地址。例如内核实现?

于 2008-10-16T09:26:51.363 回答