初始化字符指针的内存分配; [英] Memory allocation for an initialized character pointer;

查看:72
本文介绍了初始化字符指针的内存分配;的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

大家好,


如果我有一段这样的代码


void main(void)

{

char * p1 =" abcdefghijklmn";

..................... ........................

}


For p1及其指向的内容,分配的内存在哪里。在堆或堆栈上是

还是在其他一些常见的全局区域中使用
。我假设它应该在

堆栈或某个全局区域。除非

用户确实无法在堆上分配malloc存储空间是我的假设。可以有人

对编译器如何做到这一点有所了解。


如果将上面的代码改为

void main(无效)

{

char * p1;

char a [20] =" abcdefgh" ;;


strcpy(p1,a);

}


现在为p1和其他地方分配的空间在哪里在strcpy之后它指向




提前致谢。


问候,

Ar

Hi all,

If I have a piece of code something like this

void main(void)
{
char * p1="abcdefghijklmn";
.............................................

}

For p1 and whatever it points to , where is the memory allocated. Is
it on heap or stack or
some other common global area. I am assuming it should be either on
stack or some global area. Unless
a user does a malloc storage space cannot be allocated on heap is my
assumption. Can someone
throw some light on how compilers do this.

What if the above piece of code is changed to something like

void main(void)
{
char *p1;
char a[20]="abcdefgh";

strcpy(p1,a);
}

Now where is the space allocated for p1 and whatever it points to
after strcpy.

Thanks in advance.

Regards,
Ar

推荐答案

ar ***** *@gmail.com 写道:

如果我有一段这样的代码


void main(无效)

{

char * p1 =" abcdefghijklmn" ;;

............ .................................

}
If I have a piece of code something like this

void main(void)
{
char * p1="abcdefghijklmn";
.............................................

}



main的正确声明是int main(void)。请参阅

comp.lang.c常见问题解答,< http://www.c-faq.com/> ;,问题11.12a,11.12b,

11.14 a,11.14b和11.15。

The correct declaration for main is "int main(void)". See the
comp.lang.c FAQ, <http://www.c-faq.com/>, questions 11.12a, 11.12b,
11.14a, 11.14b, and 11.15.


对于p1及其指向的内容,分配的内存在哪里。在堆或堆栈上是

还是在其他一些常见的全局区域中使用
。我假设它应该在

堆栈或某个全局区域。除非

用户确实无法在堆上分配malloc存储空间是我的假设。有人可以用b $ b来了解编译器如何做到这一点。
For p1 and whatever it points to , where is the memory allocated. Is
it on heap or stack or
some other common global area. I am assuming it should be either on
stack or some global area. Unless
a user does a malloc storage space cannot be allocated on heap is my
assumption. Can someone
throw some light on how compilers do this.



p1本身的存储(指针对象)具有标准调用的内容

自动存储持续时间。这意味着它是在进入

主函数时创建的,并在退出主函数时解除分配。在一个典型的

系统中,它将被分配在堆栈上,但允许使用任何符合

的机制的
实现。标准的要求。


字符串文字的存储,abcdefghijklmn加上终止

''\'''字符,具有静态存储持续时间。该存储在程序的整个生命周期内都存在
。同样,实现是允许使用任何符合标准要求的机制。

Storage for p1 itself (the pointer object) has what the standard calls
"automatic storage duration". That means it''s created on entry to the
main function, and deallocated on exit from the main function. On a
typical system, it will be allocated on the "stack", but
implementations are allowed to use whatever mechanism meets the
standard''s requirements.

Storage for the string literal, "abcdefghijklmn" plus the terminating
''\0'' character, has "static storage duration". This storage exists
for the entire lifetime of the program. Again, implementations are
allowed to use whatever mechanism meets the standard''s requirements.


如果上面的代码被更改怎么办?类似


void main(无效)

{

char * p1;

char a [20] =" abcdefgh";


strcpy(p1,a);

}
What if the above piece of code is changed to something like

void main(void)
{
char *p1;
char a[20]="abcdefgh";

strcpy(p1,a);
}



p1和a(指针对象和数组对象)具有自动

存储持续时间;在典型的实现中,它们将被存储在堆栈中。 (但见上文)。从理论上讲,字符串

literal的内容存储在具有静态存储持续时间的某个地方,但由于

它仅用于初始化a,编译器不会实际上需要

保持它。


但是strcpy()调用很可能会失败。它试图将8

字节(abcdefg加上尾随''\ 0'')复制到任何内存p1点

到,但你没有'' t为p1指定任何内存指向。它可能

似乎正常工作,它可能会以

错误消息终止你的程序(如果你很幸运),或者它可能会破坏一些关键的

内存并导致任意不好的事情发生,仅限于操作系统强加的任何保障措施。

这是标准调用的内容未定义的行为。


您可以使用malloc()分配内存:


p1 = malloc(strlen(a)+ 1) ;

if(p1 == NULL){

/ * malloc失败,以某种方式处理错误* /

}

else {

strcpy(p1,a); / * p1现在指向一个字符串的副本* /

}


[...]


通过查看comp.lang.c

FAQ(上面的URL)可以解答很多这样的问题。


-

Keith Thompson(The_Other_Keith) ks***@mib.org < http://www.ghoti.net/~kst> ;

诺基亚

我们必须做点什么。这是事情。因此,我们必须这样做。

- Antony Jay和Jonathan Lynn,是部长

p1 and a (a pointer object and an array object) have "automatic
storage duration"; in a typical implementation, they''ll be stored on
the "stack" (but see above). Notionally, the contents of the string
literal are stored somewhere with static storage duration, but since
it''s used only to initialize a, the compiler doesn''t actually need to
keep it around.

But the strcpy() call will most likely fail. It attempts to copy 8
bytes ("abcdefg" plus the trailing ''\0'') to whatever memory p1 points
to, but you haven''t allocated any memory for p1 to point to. It might
appear to work correctly, it might terminate your program with an
error message (if you''re lucky), or it might clobber some critical
piece of memory and cause arbitrarily bad things to happen, limited
only by whatever safeguards are imposed by your operating system.
This is what the standard calls "undefined behavior".

You could allocate memory using malloc():

p1 = malloc(strlen(a) + 1);
if (p1 == NULL) {
/* malloc failed, handle the error somehow */
}
else {
strcpy(p1, a); /* p1 now points to a copy of the string */
}

[...]

Many questions like this can be answered by checking the comp.lang.c
FAQ (URL above).

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"


aruna ... @ gmail.com写道:
aruna...@gmail.com wrote:

大家好,


如果我有一段像这样的代码


void main(void)
Hi all,

If I have a piece of code something like this

void main(void)



''void''不是main()的合法返回类型,尽管许多编译器都

允许用户对其用户造成伤害。将其更改为int,并在下面添加一个

对应的''return''语句。

''void'' is not a legal return type for main(), though many compilers do
their users a disservice by allowing it. Change it to int, and add a
corresponding ''return'' statement down below.


{

char * p1 =" abcdefghijklmn";

................................ .......

}


对于p1及其指向的内容,内存在哪里分配。在堆或堆栈上是

还是在其他一些常见的全局区域中使用
。我假设它应该在

堆栈或某个全局区域。除非

用户确实无法在堆上分配malloc存储空间是我的假设。有人可以用b $ b来了解编译器如何做到这一点。
{
char * p1="abcdefghijklmn";
.............................................

}

For p1 and whatever it points to , where is the memory allocated. Is
it on heap or stack or
some other common global area. I am assuming it should be either on
stack or some global area. Unless
a user does a malloc storage space cannot be allocated on heap is my
assumption. Can someone
throw some light on how compilers do this.



内存是静态分配的。结果大致相当于

写作


int main(无效)

{

静态const char some_name [] = {'''',''b'',''c'','d'',''e'',''f'',

''g'',''h'',''我',''j'',''k'','''','''',''n'',' '\0''};

char * p1 =(char *)some_name;


这种静态内存的实际位置取决于编译器。通常情况下,Twink已经给你一个可能与你的特定编译器相关的答案,或者它可能完全是胡说八道。

唯一知道的方法就是检查你的编译器的文档,这将是一个比Twink给你的答案更好的答案。


The memory is statically allocated. The result is roughly equivalent
to writing

int main(void)
{
static const char some_name[] = {''a'', ''b'', ''c'', ''d'', ''e'', ''f'',
''g'', ''h'', ''i'', ''j'', ''k'', ''l'', ''m'', ''n'', ''\0''};
char *p1 = (char*)some_name;

The actual location for such static memory is up to your compiler. As
usual, Twink has given you an answer that might be relevant to your
particular compiler, or it might be complete nonsense. The only way to
know for sure is to check your compilers'' documentation, which would
have been a better answer than the one Twink gave you.


如果将上面的代码更改为


void main(void)

{

char * p1;

char a [20] =" abcdefgh";


strcpy(p1,a);

}


现在,在strcpy之后,为p1分配的空间和它指向

的空间在哪里。
What if the above piece of code is changed to something like

void main(void)
{
char *p1;
char a[20]="abcdefgh";

strcpy(p1,a);
}

Now where is the space allocated for p1 and whatever it points to
after strcpy.



字符串文字在初始化char *

指针时的处理方式与初始化char数组时的处理方式不同。在第一个

的情况下,为字符串

literal的内容分配静态内存,并使用指向
$ b的值初始化指针$ b数组的第一个字符。尝试将

写入该数组是不安全的。


在第二种情况下,字符串文字的内容用于

直接初始化声明的数组;没有单独的存储空间

已分配。内存是否具有静态存储持续时间或自动存储持续时间取决于数组的声明;

关于数组是否声明为同样如此

''const''。


在这种情况下,p1和a都被分配为内存和

自动存储持续时间,通常但不一定意味着它是从硬件堆栈分配的。您需要检查您的

编译器的文档,以确切了解如何处理。


每次输入语句块时,在该块中定义的对象需要重新初始化具有自动存储持续时间的
。对于你的程序来说,这不是一个问题,因为它只包含一个块,即
从未重新进入;程序中唯一的这样的对象可以像静态内存一样处理,而不会造成任何问题。

但是,在更一般的情况下,这意味着信息
每次输入块时重新初始化对象需要
必须

存储在其他地方。标准没有说明如何存储这个

信息,并且有很多不同的方法可以做到这一点。对于

小对象,数据甚至可以存储为

初始化指令的一部分,而不是存储在单独的
内存块中。


现在我们来到令人讨厌的部分。在调用

strcpy()之前,p1未初始化。因此,程序的行为是不确定的。在

原则中,即使试图读取p1的值也可能会使你的

程序中止,并且有真正的机器可能会有

发生了。在实践中,可能发生的事情是p1包含一个

位模式,你对此一无所知,包括它是否b $ b代表一个有效的内存位置。该模式将被解释为

,就好像它确实表示一个指针,并且该指针值将是传递给strcpy()的
。 strcpy()将尝试将位于a中的字符串

复制到此未知内存位置。这样做的后果

可能是灾难性的;在具有较差内存保护的系统上,如MS /

DOS,实际上可能会因写入

错误的内存位置而损坏设备;它很容易弄乱你的计算机的

配置,至少需要重启。在更多现货操作系统(包括许多操作系统,早于MS / DOS几年的时间),这样的代码就像产生内存段违规一样,
将停止您的计划。如果它没有停止,那意味着p1

碰巧指向你的程序实际拥有的内存位置

写入的权限,例如& p1 。但是,这将是分配给你的程序的内存中不可预测的部分,

很有可能制作一些其他不可预知的部分

程序失败。


简而言之:永远不要使用未初始化变量的值;是
特别注意未初始化的指针变量。你应该确定p1指向什么之前你要求strcpy()将某个东西复制到p1指向的位置。你还应该确保

无论p1指向什么,它都足以存储你要复制到它的东西。

String literals are treated differently when they initialize char*
pointers than they are when they initialize char arrays. In the first
case, static memory is allocated for the contents of the string
literal, and the pointer is initialized with a value that points to
the first character of the array. It is not safe to attempt to write
to that array.

In the second case, the contents of the string literal are used to
directly initialize the declared array; no separate storage is
allocated. Whether or not the memory has static storage duration or
automatic storage duration depends upon the declaration of the array;
the same is true about whether or not the array is declared as
''const''.

In this case, both p1 and a are both allocated as memory with
automatic storage duration, which usually, but not necessarily, means
that it is allocated from a hardware stack. You''ll need to check your
compiler''s documentation to find out exactly how this is handled.

Each time a statement block is entered, objects defined in that block
with automatic storage duration need to be re-initialized. This isn''t
an issue for your program, because it contains only one block which is
never reentered; the only such objects in your program could be
handled the same way as static memory, without causing any problems.
However, in the more general case this means that the information
needed to re-initialize the object each time the block is entered must
be stored somewhere else. The standard says nothing about how this
information is stored, and there are many different ways to do it. For
small objects, the data might even be stored as part of the
initialization instructions, rather than in a seperate block of
memory.

Now we come to the nasty part. p1 is uninitialized before the call to
strcpy(). As a result, the behavior of your program is undefined. In
principle, even attempting to read the value of p1 might make your
program abort, and there have been real machines where that would have
happened. In practice, what is likely to happen is that p1 contains a
bit pattern about which you know nothing, including whether or not it
represents a valid memory location. That pattern will be interpreted
as if it did represent a pointer, and that pointer value will be
passed to strcpy(). strcpy() will attempt to copy the string located
in ''a'' to this unknown memory location. The consequences of doing so
could be catastrophic; on systems with poor memory protection, like MS/
DOS, it was actually possible to damage devices with a write to the
wrong memory location; it was certainly easy to mess up the
configuration of your computer, requiring at least a reboot. On more
modern OSs (a category that includes many OSs that predate MS/DOS by
decades), such code is like to produce a memory segment violation,
which will halt your program. If it doesn''t halt, that means that p1
happens to point at a memory location that your program actually has
permission to write to, such as &p1. However, this will be an
unpredictable part of the memory allocated to your program, which
stands a good chance of making some other unpredictable part of your
program fail.

In short: NEVER use the value of an uninitialized variable; be
particularly careful about uninitialized pointer variables. You should
make sure that p1 points at something before you ask strcpy() to copy
something to the location p1 points at. You should also make sure that
whatever p1 points at, it is big enough to store the thing that you''re
copying to it.


9月30日,2:46 * pm,Keith Thompson< ks *** @ mib.orgwrote:
On Sep 30, 2:46*pm, Keith Thompson <ks***@mib.orgwrote:
ar ****** @ gmail.com 写道:

如果我有像这样的一段代码
If I have a piece of code something like this


void main(void)

{

* * char * p1 =" abcdefghijklmn";

* * .............................. ...............
void main(void)
{
* *char * p1="abcdefghijklmn";
* * .............................................


}
}



main的正确声明是int main(void)。


The correct declaration for main is "int main(void)".



但它不是/唯一/正确的。还有int main(int,char

**),或者您的实现支持的任何内容:


< quote>

5.1.2.2.1程序启动


1程序启动时调用的函数名为main。

实现声明此函数没有原型。它应该是返回类型为int并且没有参数定义的




int main(void){/ * ... * /}


或两个参数(这里称为argc和argv,虽然可以使用任何

名称,因为它们是它们所在的函数的本地名称)

声明):


int main(int argc,char * argv []){/ * ... * /}


或等价物; 9)或其他一些实施定义的方式。


< end quote>


OP显示的原型也是正确的。


Sebastian

But it''s not the /only/ correct one. There''s also "int main(int, char
**)", or anything your implementation supports:

<quote>
5.1.2.2.1 Program startup

1 The function called at program startup is named main. The
implementation declares no prototype for this function. It shall be
defined with a return type of int and with no parameters:

int main(void) { /* ... */ }

or with two parameters (referred to here as argc and argv, though any
names may be used, as they are local to the function in which they are
declared):

int main(int argc, char *argv[]) { /* ... */ }

or equivalent;9) or in some other implementation-defined manner.

<end quote>

Thus, the prototype shown by the OP is also correct.

Sebastian


这篇关于初始化字符指针的内存分配;的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆