String and null character

C

Chapman

Some questions about strings: this is the extracted piece of my test code:

/** **/

char *arry;
arry = malloc(30*sizeof(arry));

arry[0] = 'B';
arry[1] = 'S';
arry[2] = 'c';

/** **/

The questions are:

1. Now does the variable arry contain the null character immediately because
of malloc?

2. or I should append '0' at arry[3] ? (which in fact what I did next, but
when testing the compiler without '\0', it worked (??)

Because in both cases (whether I append '\0' or not), if I use the
functions atoi or any other string functions, the compiler
does not give warning or error message, what happened?

Thanks in advance
 
I

Irrwahn Grausewitz

Chapman said:
Some questions about strings: this is the extracted piece of my test code:

/** **/

char *arry;
arry = malloc(30*sizeof(arry));
You allocate memory to hold 30 pointers-to-character, which is obviously
not your intention; make this:

arry = malloc( 30 * sizeof *arry );
arry[0] = 'B';
arry[1] = 'S';
arry[2] = 'c';

/** **/

The questions are:

1. Now does the variable arry contain the null character immediately because
of malloc? No.


2. or I should append '0' at arry[3] ?
If you intend to use it as a string: yes.
(which in fact what I did next, but
when testing the compiler without '\0', it worked (??)
This was just (bad) luck; virtually *anything* could have happened.
Because in both cases (whether I append '\0' or not), if I use the
functions atoi or any other string functions, the compiler
does not give warning or error message, what happened?
The compiler cannot check something that gets allocated and altered at
run-time. You have to make sure your strings are '\0'-terminated.

Regards

Irrwahn
 
J

Jeff

Chapman said:
Some questions about strings: this is the extracted piece of my test code:

/** **/

char *arry;
arry = malloc(30*sizeof(arry));

If you want to allocate a buffer to hold a string, you should write

arry = malloc(30); /* This way is correct. "sizeof char" is defined as 1
byte, you don't need to use sizeof on this */

or

arry = malloc(30 * sizeof *arry) /* You should use sizeof on "*arry" (which
is a single char), not char* (which is a pointer. I think this is not what
you want, right ? ). Also, don't use "sizeof( variable )" , use "sizeof
variable" or "sizeof(variable type)" instead. */

arry[0] = 'B';
arry[1] = 'S';
arry[2] = 'c';

/** **/

The questions are:

1. Now does the variable arry contain the null character immediately because
of malloc?

No. If you want to fill all the elements by zero after allocated, you can
consider "calloc"
2. or I should append '0' at arry[3] ?

Yes.

(which in fact what I did next, but
when testing the compiler without '\0', it worked (??)

Don't believe this, you are just lucky.
Because in both cases (whether I append '\0' or not), if I use the
functions atoi or any other string functions, the compiler
does not give warning or error message, what happened?

Why should it give warning or error ?
 
J

John Bode

Chapman said:
Some questions about strings: this is the extracted piece of my test code:

/** **/

char *arry;
arry = malloc(30*sizeof(arry));

ITYM

arry = malloc (30 * sizeof *arry);

The type of arry is char*; the type of *arry is char.
arry[0] = 'B';
arry[1] = 'S';
arry[2] = 'c';

/** **/

The questions are:

1. Now does the variable arry contain the null character immediately because
of malloc?

No. malloc() does not initialize the allocated memory to any specific
value. Assume it contains garbage. If you need the memory to be
initialized to 0 when allocating it, use calloc().
2. or I should append '0' at arry[3] ? (which in fact what I did next, but
when testing the compiler without '\0', it worked (??)

Luck. The memory you allocated just happened to be zeroed out, but
you can't rely on that behavior.
Because in both cases (whether I append '\0' or not), if I use the
functions atoi or any other string functions, the compiler
does not give warning or error message, what happened?

Thanks in advance

The string functions will walk through memory starting at the point
you specify until they see a nul terminator (0). If you forget to put
a nul terminator in your buffer, the string functions will happily
read or write past it until they either find one or try to read or
write a protected or invalid memory address, causing a trap.

Either way, forgetting to append a nul terminator to a dynamically
allocated buffer is a condition that only occurs when the program is
run; your compiler can't warn you about something that it can't
predict.
 
C

Chapman

Jeff said:
If you want to allocate a buffer to hold a string, you should write

arry = malloc(30); /* This way is correct. "sizeof char" is defined as 1
byte, you don't need to use sizeof on this */

or

arry = malloc(30 * sizeof *arry) /* You should use sizeof on "*arry" (which
is a single char), not char* (which is a pointer. I think this is not what
you want, right ? ). Also, don't use "sizeof( variable )" , use "sizeof
variable" or "sizeof(variable type)" instead. */
Thanks for the explanation Jeff.
The questions are:

1. Now does the variable arry contain the null character immediately because
of malloc?

No. If you want to fill all the elements by zero after allocated, you can
consider "calloc"
2. or I should append '0' at arry[3] ?

Yes.

(which in fact what I did next, but
when testing the compiler without '\0', it worked (??)

Don't believe this, you are just lucky.

I could not believe it either, and everytime I run the program without
appending the '\0', it was alright.
Something wrong with gcc ? Following the standard, I appended '\0', just
curious why it happened without warning.
It is not about being lucky, or probably the function definitions with gcc
is 'relaxed' about the '\0' ??
Why should it give warning or error ?

It should gave me error when I run it and the string did not have the '\0',
but it didn't
 
M

Malcolm

Chapman said:
I could not believe it either, and everytime I run the program without
appending the '\0', it was alright.
Something wrong with gcc ? Following the standard, I appended '\0',
just curious why it happened without warning.
It is not about being lucky, or probably the function definitions with gcc
is 'relaxed' about the '\0' ??
String functions will generally fail if passed a non-NUL terminated string.

However it is quite common for garbage memory to contain a lot of zeroes,
and you must have just hit a zero. It's also possible that your version of
malloc() zeroes memory, however you can't rely on this behaviour.
It should gave me error when I run it and the string did not have the
'\0', but it didn't
The following code is OK

char *str = calloc(1,100);
str[0] = 'F';
str[1] = 'R';
str[2] = 'E';
str[3] = 'D';
printf("%s\n", str);

This is because calloc() is guaranteed to zero memory.

The compiler is not clever enough to distinguish between the function
calloc() and malloc(), and realise that in your case you are setting up a
string which is not NUL-terminated. This is because C is such a low-level
language - strings are just handled as arrays of bytes in memory.
 
I

Irrwahn Grausewitz

Malcolm said:
String functions will generally fail if passed a non-NUL terminated string.
^^^^^^^^^^^^^^^^^^^
Nit-pick: ... will generally invoke undefined behaviour ...

<SNIP>

Regards

Irrwahn
 
M

Minti

Chapman said:
Jeff said:
If you want to allocate a buffer to hold a string, you should write

arry = malloc(30); /* This way is correct. "sizeof char" is defined as 1
byte, you don't need to use sizeof on this */

or

arry = malloc(30 * sizeof *arry) /* You should use sizeof on "*arry" (which
is a single char), not char* (which is a pointer. I think this is not what
you want, right ? ). Also, don't use "sizeof( variable )" , use "sizeof
variable" or "sizeof(variable type)" instead. */
Thanks for the explanation Jeff.
The questions are:

1. Now does the variable arry contain the null character immediately because
of malloc?

No. If you want to fill all the elements by zero after allocated, you can
consider "calloc"
2. or I should append '0' at arry[3] ?

Yes.

(which in fact what I did next, but
when testing the compiler without '\0', it worked (??)

Don't believe this, you are just lucky.

I could not believe it either, and everytime I run the program without
appending the '\0', it was alright.
Something wrong with gcc ? Following the standard, I appended '\0', just
curious why it happened without warning.
It is not about being lucky, or probably the function definitions with gcc
is 'relaxed' about the '\0' ??
Why should it give warning or error ?

It should gave me error when I run it and the string did not have the '\0',
but it didn't

You run it on some other platform it would possibly give you an error
eventhough the chances of having a runtime error are more than those
of a compile time error. It is as a matter of fact difficult to get to
know if you are setting or not setting the null character, consider
this

while ( some_condition )
{
c = getchar();
malloced_character_array [ i ] = c;
i += 1;
}

During complile time it is quite difficult to determine as to if what
the user would set the value to be.


BTW compiler is not supposed to give any error and I think I won't be
wrong if I could say that the compiler is not supposed to give error
even for a completly invalid program

even if you type garbage in your source file, it is quite unreasonable
but true that a compiler can give you a message of the form of

"succesfully built".


HTH


PS IIRC someone had a website which showed a missile heading back to
the carrier which shot them in case of program exhibiting a UB, can
anybody provide that link.
 
J

Jack Klein

^^^^^^^^^^^^^^^^^^^
Nit-pick: ... will generally invoke undefined behaviour ...
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Even more nit pick: will ALWAYS invoke undefined behavior, which
generally causes a program to fail.
<SNIP>

Regards

Irrwahn

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++ ftp://snurse-l.org/pub/acllc-c++/faq
 
I

Irrwahn Grausewitz

(e-mail address removed) (Minti) wrote:

BTW compiler is not supposed to give any error and I think I won't be
wrong if I could say that the compiler is not supposed to give error
even for a completly invalid program

even if you type garbage in your source file, it is quite unreasonable
but true that a compiler can give you a message of the form of

"succesfully built".
<SNIP>

Hmm, consider this quote from n843:

5.1.1.3 Diagnostics

[#1] A conforming implementation shall produce at least one
diagnostic message (identified in an implementation-defined
manner) if a preprocessing translation unit or translation
unit contains a violation of any syntax rule or constraint,
even if the behavior is also explicitly specified as
undefined or implementation-defined. Diagnostic messages
need not be produced in other circumstances.7)

[#2] EXAMPLE An implementation shall issue a diagnostic for
the translation unit:

char i;
int i;

because in those cases where wording in this International
Standard describes the behavior for a construct as being
both a constraint error and resulting in undefined behavior,
the constraint error shall be diagnosed.

[...]

Regards

Irrwahn
 
M

Mark McIntyre

^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Even more nit pick: will ALWAYS invoke undefined behavior, which
generally causes a program to fail.

super nitpick: which MAY cause a program to fail, or alternatively to
succeed by pure chance some of the time, or to merely seem to succeed
but in fact to be storing up trouble for later eg when demo'ing to a
client. The latter pair are in my experience by far the commonest.
 
M

Malcolm

Mark McIntyre said:
super nitpick: which MAY cause a program to fail, or alternatively to
succeed by pure chance some of the time, or to merely seem to
succeed but in fact to be storing up trouble for later eg when demo'ing
to a client. The latter pair are in my experience by far the commonest.
We're talking about passing a string which is not NUL-terminated to a string
function, as opposed to passing a string which has been accidentally
terminated by a NUL (as the OP seemed to be finding).

A few functions, like strchr(), will succeed in some circumstances. Most,
like strlen(), will find it very difficult to produce "correct" results.
strlen() will probably charge through memory until it hits a zero byte,
which will either result in an incorrect answer or a segmentation fault.
Most string functions are similar.
If you have undefined behaviour, and the string functions seem to be working
OK, it is unlikely that you are passing non-NUL terminated strings to these
functions, and UB produces the expected results. It is probable that the
byte following the string happens to be zero.
 
M

Minti

Irrwahn Grausewitz said:
(e-mail address removed) (Minti) wrote:

BTW compiler is not supposed to give any error and I think I won't be
wrong if I could say that the compiler is not supposed to give error
even for a completly invalid program

even if you type garbage in your source file, it is quite unreasonable
but true that a compiler can give you a message of the form of

"succesfully built".
<SNIP>

Hmm, consider this quote from n843:

5.1.1.3 Diagnostics

[#1] A conforming implementation shall produce at least one
diagnostic message (identified in an implementation-defined
manner) if a preprocessing translation unit or translation
unit contains a violation of any syntax rule or constraint,
even if the behavior is also explicitly specified as
undefined or implementation-defined. Diagnostic messages
need not be produced in other circumstances.7)

[#2] EXAMPLE An implementation shall issue a diagnostic for
the translation unit:

char i;
int i;

because in those cases where wording in this International
Standard describes the behavior for a construct as being
both a constraint error and resulting in undefined behavior,
the constraint error shall be diagnosed.

[...]

Thanks for correction.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top