String Literals

T

thedude

If I used this return statement in a c function

return (int)* "hello world";

From what I know the calling function will only retrieve the character
'h', right ?

Is it right to assume that nevertheless, read only memory was
allocated for the entire string "hello world" , And if so can that
memory(Or the rest of the characters) be accessed somehow ?

Thanks in advance.
 
J

Jens Thoms Toerring

thedude said:
If I used this return statement in a c function
return (int)* "hello world";

Why would you do that?
From what I know the calling function will only retrieve the character
'h', right ?

The caller will receive the address of the string literal
cast to an int pointer. What that should be good for is
beyond me since the correct type of the address is const
char pointer. This conversion to int pointer invokes un-
defined behaviour. The standard allows to convert an ob-
ject pointer (e.g. an int *) to a void (or, for historical
reasons, char) pointer and then the back-conversion of this
result, but not from every object pointer type to each other
object pointer type (on some architectures different types
of pointers may have e.g. different sizes).

If you dereference the int pointer you got back from the func-
tion you may get a bus error since an int may have more strict
alignment requirements than a char, so the string may start at
an address that's not suitable aligned for accesses via an int
pointer (even if the cast from const char * to int * didn't
mess up the address).
Is it right to assume that nevertheless, read only memory was
allocated for the entire string "hello world"

Yes, with and without the "nevertheless";-)
And if so can that
memory(Or the rest of the characters) be accessed somehow ?

Yes and no. If your machine actually doesn't do anything
bad when converting from const char * to int * then you may
be able to convert the returned pointer back to const char *;
so you can get at the string. But why rely on that? If your
function is supposed to return a generic pointer you should
use a void pointer.
Regards, Jens
 
S

Sebastian

If I used this return statement in a c function

return (int)* "hello world";

From what I know the calling function will only retrieve the
character 'h', right ?

Please provide a code snippet that actually compiles or at least is
supposed to compile. I'm guessing you meant something like this:

char* foo() {
return "hello world";
}

In this case the function returns a pointer that points to the
character 'h', yes. But all the characters are placed consecutivly in
memory.
Is it right to assume that nevertheless, read only memory was
allocated for the entire string "hello world" ,

Yes. At least you are not allowed to change any of it. Prefer to use
the type "const char*" in such cases. This makes any mutation attemp a
compile-time error.

int main(void) {
const char *p = "hello";
p[0] = 'H'; // compile-time error
return 0;
}

whereas without "const" this program would probably compile on all
compilers but invoke undefined behaviour.
And if so can that memory(Or the rest of the characters) be
accessed somehow ?

Sure. A string literal is a character array with static storage. As
such, all the characters are stored linearly in memory.

#include <stdio.h>

int main(void) {
const char *p = "hello";
while (*p) printf("%c",*p++);
puts("\n");
return 0;
}

This program iterates through the whole string by incrementing the
pointer until the null terminator is reached. You see, the string
literal "hello" is an array of 6 characters: 'h', 'e', 'l', 'l', 'o',
'\0'.

Cheers
SG
 
J

Jens Thoms Toerring

Tim Rentsch said:
(e-mail address removed) (Jens Thoms Toerring) writes:
thedude said:
If I used this return statement in a c function
return (int)* "hello world";

Why would you do that?
From what I know the calling function will only retrieve the character
'h', right ?

The caller will receive the address of the string literal
cast to an int pointer. [snip]
You may want to look again. The cast is to (int),
not to (int*).

Ooops, where are my glasses when I need them? Thanks...

Regards, Jens
 
T

Tim Rentsch

thedude said:
If I used this return statement in a c function

return (int)* "hello world";

From what I know the calling function will only retrieve the character
'h', right ?

Only the first character of the string literal will
be accessed, if that's what you mean.
Is it right to assume that nevertheless, read only memory was
allocated for the entire string "hello world" ,

It may be but it doesn't have to be. An implementation
may (legally) compile this the same as it would compile

return (int) 'h';
And if so can that
memory(Or the rest of the characters) be accessed somehow ?

Memory for the string literal need not exist in the
actual compiled program.
 
T

Tim Rentsch

Sebastian said:
If I used this return statement in a c function

return (int)* "hello world";

From what I know the calling function will only retrieve the
character 'h', right ?

Please provide a code snippet that actually compiles or at least is
supposed to compile. [snip]

I'm guessing you misread the example line. That's '(int)*',
not '(int*)'.
 
S

Sebastian

Please provide a code snippet that actually compiles or at least is
supposed to compile. I'm guessing you meant something like this:

  char* foo() {
    return "hello world";
  }

Oops.

return (int)* "hello world"

is actually legal for a function that returns int. I was assuming you
made a typo and meant (int*). But it also makes little sense. *"hello
world" is pretty much equivalent to 'h'. In that case the function
returns only an integer representing the 'h' character and you won't
be able to retrieve anything else because the address is lost.

You should have posted the whole function's body.
 
T

thedude

Thanks for your response Tim R.(and everyone else)

Yes I did mean dereference the string literal and cast it to an int.

Problem is, That function is in an "obnoxious" header file(API) I am
supposed to use(ie not in my control).
And I saw that only the first character was being returned, And why
they did that was beyond me too.

Ravi

Please provide a code snippet that actually compiles or at least is
supposed to compile. [snip]

I'm guessing you misread the example line.  That's '(int)*',
not '(int*)'.
 
M

Malcolm McLean

Thanks for your response Tim R.(and everyone else)

Yes I did mean dereference the string literal and cast it to an int.

Problem is, That function is in an "obnoxious" header file(API) I am
supposed to use(ie not in my control).
And I saw that only the first character was being returned, And why
they did that was beyond me too.
It seems odd.
However it's quite common to pass chars around as ints. For some
reason the character 'h' must have been required, and the reason it
was 'h' and not some other value was that 'h' is the initial character
of the string "hello world". That would make sense - if the crucial
string turns to "goodbye cruel world" at some later date the source of
the 'h' is documented for the maintainer.
 
D

Denis McMahon

return (int)* "hello world";

From what I know the calling function will only retrieve the character
'h', right ?

Is it right to assume that nevertheless, read only memory was
allocated for the entire string "hello world" , And if so can that
memory(Or the rest of the characters) be accessed somehow ?

Why not write the code, compile it and try it? Of course, the answer
that you get might only apply to your compiler, but then that's often
the case when people step outside the boundaries of sensible code and
into the realm of doing bloody stupid things to see what happens.

Rgds

Denis McMahon
 
D

Denis McMahon

Why not write the code, compile it and try it? Of course, the answer
that you get might only apply to your compiler, but then that's often
the case when people step outside the boundaries of sensible code and
into the realm of doing bloody stupid things to see what happens.

Following up, and having tested, there's no way to see the remainder of
the string literal from the calling function:

#include <stdio.h>

int f() {
return (int)* "hello world";
}

int main () {
int i;
i = f();
printf ("%c %i\n",(char)i,i);
}

I get:

h 104

The calling procedure allocates storage for an int, and receives that
int. Any pointer to the string literal only exists within the function f
and is not visible to the calling procedure.

The address of the integer i in the calling procedure is defined by the
calling procedure, so even if it is dereferenced to a pointer and cast
to char, it's not going to contain anything other than (int)'h'.
#include <stdio.h>

int f() {
return (int)* "hello world";
}

int main () {
int i;
char *c;
int j;

i = f();
c = (char *) &i;
printf ("%c %d\n",(char)i,i);
printf ("%s\n---\n",c);

for (j = 0; j < 12; j++) {
printf ("%c %d\n",(char)c[j],c[j]);
}
}

I get:

h 104
h
---
h 104
0
0
0
0
0
0
0
0
0
0
0

Your mileage may vary.

Rgds

Denis McMahon
 
K

Keith Thompson

thedude said:
If I used this return statement in a c function

return (int)* "hello world";

From what I know the calling function will only retrieve the character
'h', right ?

Right. Incidentally, the cast is unnecessary; whatever type the
enclosing function returns, the result of *"hello world" (which is
of type char) will be implicitly converted to the required type.
Or if the return type isn't numeric, the cast won't help. But I'm
guessing that the function returns int.

I can't think of any reason to write the above rather than just

return 'h';

unless perhaps the "hello world" is the result of a macro expansion.
Is it right to assume that nevertheless, read only memory was
allocated for the entire string "hello world" , And if so can that
memory(Or the rest of the characters) be accessed somehow ?

In the abstract machine, the string literal implies the creation
of a static object of type "array of char". (It's not necessarily
read-only; attempting to modify it invokes undefined behavior.)

But in this case, the only thing the program does with that array is
retrieve the value of its first element, the 'h'. You *could* have
accessed the rest of the array, but you didn't. Because of that,
the compiler is free to eliminate the rest of the array, generating
code equivalent to "return 'h';". The function returns (a copy of)
the *value* 'h', not the address where it's stored, so there's no
way for a caller to use the result to get at the "ello world".
 
T

thedude

To follow up ...

I turned out to be a in a bug in the header file that I need to deal
with for now.
The intention was to return the first four bytes of the string cast as
an int.

So what was intended should have been written as

return *(int *) "hello world"

Regarding me writing up the code. Yes, I did have a few shots at it,
But was not successful(seg. faults) - And that's when I wondered if
there was a way to do it. Phew, Accusations galore :)

Ravi
 

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,982
Messages
2,570,185
Members
46,737
Latest member
Georgeengab

Latest Threads

Top