initialisation of a char pointer using char *s = "something"

B

Brice Rebsamen

Reading the code from showkey.c (from package kbd) I found this type
of code:

char *m;
m = "RAW";

See below for the complete code. How can this work? I would have used
strdup, or allocation of the memory for m (static or dynamic) then
strncpy.

Thanks
Brice


static void
get_mode(void) {
char *m;

if (ioctl(fd, KDGKBMODE, &oldkbmode)) {
perror("KDGKBMODE");
exit(1);
}
switch(oldkbmode) {
case K_RAW:
m = "RAW"; break;
case K_XLATE:
m = "XLATE"; break;
case K_MEDIUMRAW:
m = "MEDIUMRAW"; break;
case K_UNICODE:
m = "UNICODE"; break;
default:
m = _("?UNKNOWN?"); break;
}
printf(_("kb mode was %s\n"), m);
if (oldkbmode != K_XLATE) {
printf(_("[ if you are trying this under X, it might not work\n"
"since the X server is also reading /dev/console ]\n"));
}
printf("\n");
}
 
I

Ian Collins

Brice said:
Reading the code from showkey.c (from package kbd) I found this type
of code:

char *m;
m = "RAW";
The character pointer m (which should probably be a const char*) points
to the string literal "RAW".
See below for the complete code. How can this work? I would have used
strdup, or allocation of the memory for m (static or dynamic) then
strncpy.
Remember m it a pointer.
 
C

Chris Thomasson

WANG Cong said:
On Tue, 11 Mar 2008 21:10:20 -0700,Brice Rebsamen wrote:


In C, you should treat the string "RAW" as a pointer to char.
[...]

What about treating it as a pointer to a const char?

[...]
 
P

Peter Nilsson

Brice Rebsamen said:
Reading the code from showkey.c (from package kbd) I
found this type of code:

char *m;
m = "RAW";

See below for the complete code. How can this work?

What makes you think it can't?

I suspect your confusion stems from m not being const
qualified, and string literals having type char[] in C.
I would have used strdup, or allocation of the memory
for m (static or dynamic) then strncpy.
<snip>

Why bother?

Take a look at the following and see if the penny drops...

#include <stdio.h>

void foo(const char *m)
{
puts(m);
}

void bar(void)
{
const char *m = "Hello"; /* what's the diff? */
puts(m);
}

int main(void)
{
foo("Hello");
bar();
return 0;
}

Given the points I mentioned earlier, realise that
I could leave out the const-s, though it wouldn't
be good form.
 
J

J. J. Farrell

Brice said:
Reading the code from showkey.c (from package kbd) I found this type
of code:

char *m;
m = "RAW";

See below for the complete code. How can this work? I would have used
strdup, or allocation of the memory for m (static or dynamic) then
strncpy.

...

This is not a meaningful question. It obviously does work, and my
immediate response to your question was "how can it not work". You need
to explain why you find this surprising, then we'll be able to sort out
your confusion.
 
B

Brice Rebsamen

Brice Rebsamen said:
Reading the code from showkey.c (from package kbd) I
found this type of code:
char *m;
m = "RAW";
See below for the complete code. How can this work?

What makes you think it can't?

I suspect your confusion stems from m not being const
qualified, and string literals having type char[] in C.
I would have used strdup, or allocation of the memory
for m (static or dynamic) then strncpy.

<snip>

Why bother?

Take a look at the following and see if the penny drops...

#include <stdio.h>

void foo(const char *m)
{
puts(m);
}

void bar(void)
{
const char *m = "Hello"; /* what's the diff? */
puts(m);
}

int main(void)
{
foo("Hello");
bar();
return 0;
}

Given the points I mentioned earlier, realise that
I could leave out the const-s, though it wouldn't
be good form.


Still I'm confused. Take a look at the following:

const char *getm1(void) { char m[] = "Hello"; return m; }
const char *getm2(void) { return "Hello"; }

getm1 raises a warning about returning the address of a local variable
and returns a corrupted string. This I have known for a long time. My
explanation is that the memory is released when the function returns,
therefore whatever happens to m is undefined (possibly overwritten).
I don't understand why it's not the case with getm2().
 
W

WANG Cong

On Tue, 11 Mar 2008 21:10:20 -0700,Brice Rebsamen wrote:
Reading the code from showkey.c (from package kbd) I found this type of
code:

char *m;
m = "RAW";

See below for the complete code. How can this work? I would have used
strdup, or allocation of the memory for m (static or dynamic) then
strncpy.

In C, you should treat the string "RAW" as a pointer to char.
Thanks
Brice


static void
get_mode(void) {
char *m;

if (ioctl(fd, KDGKBMODE, &oldkbmode)) {
perror("KDGKBMODE");
exit(1);
}
switch(oldkbmode) {
case K_RAW:
m = "RAW"; break;
case K_XLATE:
m = "XLATE"; break;
case K_MEDIUMRAW:
m = "MEDIUMRAW"; break;
case K_UNICODE:
m = "UNICODE"; break;
default:
m = _("?UNKNOWN?"); break;


Hmm, you must have a function named "_", and it takes a (const) char*
parameter, right?
 
B

Brice Rebsamen

What makes you think it can't?
I suspect your confusion stems from m not being const
qualified, and string literals having type char[] in C.
I would have used strdup, or allocation of the memory
for m (static or dynamic) then strncpy.

Why bother?
Take a look at the following and see if the penny drops...
#include <stdio.h>
void foo(const char *m)
{
puts(m);
}
void bar(void)
{
const char *m = "Hello"; /* what's the diff? */
puts(m);
}
int main(void)
{
foo("Hello");
bar();
return 0;
}
Given the points I mentioned earlier, realise that
I could leave out the const-s, though it wouldn't
be good form.

Still I'm confused. Take a look at the following:

const char *getm1(void) { char m[] = "Hello"; return m; }
const char *getm2(void) { return "Hello"; }

getm1 raises a warning about returning the address of a local variable
and returns a corrupted string. This I have known for a long time. My
explanation is that the memory is released when the function returns,
therefore whatever happens to m is undefined (possibly overwritten).
I don't understand why it's not the case with getm2().

Messages come really fast here! I found a clear answer in c-faq 1.32.
Thanks all.
 
W

WANG Cong

On Tue, 11 Mar 2008 21:52:52 -0700,Chris Thomasson wrote:
WANG Cong said:
On Tue, 11 Mar 2008 21:10:20 -0700,Brice Rebsamen wrote:


In C, you should treat the string "RAW" as a pointer to char.
[...]

What about treating it as a pointer to a const char?

Yes, more correct. Its conversion to char* is only permitted for C
compatibility indeed.
 
W

WANG Cong

On Wed, 12 Mar 2008 07:06:19 +0000,WANG Cong wrote:
On Tue, 11 Mar 2008 21:52:52 -0700,Chris Thomasson wrote:
WANG Cong said:
On Tue, 11 Mar 2008 21:10:20 -0700,Brice Rebsamen wrote:

Reading the code from showkey.c (from package kbd) I found this type
of code:

char *m;
m = "RAW";

See below for the complete code. How can this work? I would have used
strdup, or allocation of the memory for m (static or dynamic) then
strncpy.

In C, you should treat the string "RAW" as a pointer to char.
[...]

What about treating it as a pointer to a const char?

Yes, more correct. Its conversion to char* is only permitted for C
compatibility indeed.

See also Question 11.8b of C-faq.
 
K

Keith Thompson

Ian Collins said:
The character pointer m (which should probably be a const char*) points
to the string literal "RAW".

Remember m it a pointer.

I suspect Brice's confusion is based not on the fact that m is a
pointer (it obviously is, since it's declared that way), but on the
fact that "RAW" isn't a pointer.

If you're unfamiliar with C, you know that "=" is an assignment
operator, and that it causes the value of the right hand side to be
copied to the object named by the left hand side. In this case, you
might assume that the characters 'R', 'A', and 'W' (and the trailing
'\0') are going to be copied -- but it ain't so.

A string literal is an array of char. The trick is that, like any
expression of array type, it's implicitly converted to a pointer to
the array's first element in most contexts. This conversion doesn't
happen when the array is the operand of a unary "&" or "sizeof"
operator, or when it's a string literal use to initialize an array.

(In case you were wondering, the last case doesn't apply here, since
(a) it's an assignment, not an initializer, and (b) the object being
initialized^H^H^H^H^H^H^H^H^H^H^H assigned to isn't an array.)

So the assignment
m = "RAW";
copies, not the string "RAW", but the address of its first character,
into m.

The relationship between arrays and pointers in C can be confusing,
and some features of the language almost seem to have been designed to
maintain that confusion. The best cure I know of is to read and
understand section 6 of the comp.lang.c FAQ, <http://www.c-faq.com/>.
 

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

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top