Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #75804 > unrolled thread

double strtod( const char *nPtr, char **endPrt);

Started byG G <gdotone@gmail.com>
First post2015-11-11 22:55 -0800
Last post2015-11-12 16:57 -0800
Articles 20 on this page of 33 — 11 participants

Back to article view | Back to comp.lang.c


Contents

  double strtod( const char *nPtr, char **endPrt); G G <gdotone@gmail.com> - 2015-11-11 22:55 -0800
    Re: double strtod( const char *nPtr, char **endPrt); Richard Heathfield <rjh@cpax.org.uk> - 2015-11-12 07:24 +0000
      Re: double strtod( const char *nPtr, char **endPrt); G G <gdotone@gmail.com> - 2015-11-11 23:42 -0800
    Re: double strtod( const char *nPtr, char **endPrt); Keith Thompson <kst-u@mib.org> - 2015-11-12 08:31 -0800
      Re: double strtod( const char *nPtr, char **endPrt); supercat@casperkitty.com - 2015-11-12 08:52 -0800
      Re: double strtod( const char *nPtr, char **endPrt); G G <gdotone@gmail.com> - 2015-11-12 09:43 -0800
        Re: double strtod( const char *nPtr, char **endPrt); Richard Heathfield <rjh@cpax.org.uk> - 2015-11-12 17:59 +0000
        Re: double strtod( const char *nPtr, char **endPrt); Eric Sosman <esosman@comcast-dot-net.invalid> - 2015-11-12 13:10 -0500
        Re: double strtod( const char *nPtr, char **endPrt); James Kuyper <jameskuyper@verizon.net> - 2015-11-12 13:19 -0500
        Re: double strtod( const char *nPtr, char **endPrt); Keith Thompson <kst-u@mib.org> - 2015-11-12 11:32 -0800
          Re: double strtod( const char *nPtr, char **endPrt); supercat@casperkitty.com - 2015-11-12 12:17 -0800
            Re: double strtod( const char *nPtr, char **endPrt); Keith Thompson <kst-u@mib.org> - 2015-11-12 12:48 -0800
              Re: double strtod( const char *nPtr, char **endPrt); supercat@casperkitty.com - 2015-11-12 13:39 -0800
                Re: double strtod( const char *nPtr, char **endPrt); glen herrmannsfeldt <gah@ugcs.caltech.edu> - 2015-11-12 23:24 +0000
                Re: double strtod( const char *nPtr, char **endPrt); Keith Thompson <kst-u@mib.org> - 2015-11-12 17:14 -0800
                  Re: double strtod( const char *nPtr, char **endPrt); supercat@casperkitty.com - 2015-11-12 17:42 -0800
                    Re: double strtod( const char *nPtr, char **endPrt); Keith Thompson <kst-u@mib.org> - 2015-11-12 18:20 -0800
              Re: double strtod( const char *nPtr, char **endPrt); glen herrmannsfeldt <gah@ugcs.caltech.edu> - 2015-11-12 23:15 +0000
                Re: double strtod( const char *nPtr, char **endPrt); Eric Sosman <esosman@comcast-dot-net.invalid> - 2015-11-12 18:30 -0500
                  Re: double strtod( const char *nPtr, char **endPrt); supercat@casperkitty.com - 2015-11-12 16:47 -0800
                  Re: double strtod( const char *nPtr, char **endPrt); Keith Thompson <kst-u@mib.org> - 2015-11-12 18:07 -0800
                  Re: double strtod( const char *nPtr, char **endPrt); glen herrmannsfeldt <gah@ugcs.caltech.edu> - 2015-11-13 02:41 +0000
                  Re: double strtod( const char *nPtr, char **endPrt); glen herrmannsfeldt <gah@ugcs.caltech.edu> - 2015-11-13 02:53 +0000
          Re: double strtod( const char *nPtr, char **endPrt); G G <gdotone@gmail.com> - 2015-11-12 12:17 -0800
    Re: double strtod( const char *nPtr, char **endPrt); Malcolm McLean <malcolm.mclean5@btinternet.com> - 2015-11-12 12:34 -0800
      Re: double strtod( const char *nPtr, char **endPrt); Ben Bacarisse <ben.usenet@bsb.me.uk> - 2015-11-12 23:54 +0000
        Re: double strtod( const char *nPtr, char **endPrt); Malcolm McLean <malcolm.mclean5@btinternet.com> - 2015-11-12 16:23 -0800
          Re: double strtod( const char *nPtr, char **endPrt); Ian Collins <ian-news@hotmail.com> - 2015-11-13 14:09 +1300
            Re: double strtod( const char *nPtr, char **endPrt); Malcolm McLean <malcolm.mclean5@btinternet.com> - 2015-11-12 17:31 -0800
              Re: double strtod( const char *nPtr, char **endPrt); Ian Collins <ian-news@hotmail.com> - 2015-11-13 14:46 +1300
          Re: double strtod( const char *nPtr, char **endPrt); Ben Bacarisse <ben.usenet@bsb.me.uk> - 2015-11-13 02:07 +0000
          Re: double strtod( const char *nPtr, char **endPrt); David Brown <david.brown@hesbynett.no> - 2015-11-13 08:48 +0100
      Re: double strtod( const char *nPtr, char **endPrt); Keith Thompson <kst-u@mib.org> - 2015-11-12 16:57 -0800

Page 1 of 2  [1] 2  Next page →


#75804 — double strtod( const char *nPtr, char **endPrt);

FromG G <gdotone@gmail.com>
Date2015-11-11 22:55 -0800
Subjectdouble strtod( const char *nPtr, char **endPrt);
Message-ID<fcf0991b-eb10-4594-8745-0ae2fc15721f@googlegroups.com>
double strtod( const char *nPtr, char **endPrt );
(and functions like it)

nPtr is a pointer to a character constant

endPtr is a pointer to a pointer to a character or
endPtr is a pointer to a pointer of type character?
 

nPtr is not changeable. i mean what nPtr points
to is not changeable.

endPtr is a pointer which points to another to a character 
that is allowed to change?

this function will search a string to find characters that can
be changed into a double?

in this function, char **endPtr requires the address of a 
pointer?

example program: from C How to Program, Deitel and Deitel

#include <stdio.h>
#include <stdlib.h>

int main( void )
{

    const char *string = "51.2% are admitted";

    double d;
    char *stringPtr;

    d = strtod( string, &stringPtr );

    printf( "The string \"%s\" is converted to the \n", string );
    printf( "double value %.2f and the string \"%s\"\n", d, stringPtr );

} // end main


char *stringPtr only needs to be a pointer, because it will
point to the remaining string.

[toc] | [next] | [standalone]


#75805

FromRichard Heathfield <rjh@cpax.org.uk>
Date2015-11-12 07:24 +0000
Message-ID<n21emo$h1u$1@dont-email.me>
In reply to#75804
On 12/11/15 06:55, G G wrote:
> double strtod( const char *nPtr, char **endPrt );
> (and functions like it)
>
> nPtr is a pointer to a character constant
>
> endPtr is a pointer to a pointer to a character or
> endPtr is a pointer to a pointer of type character?

endPtr is a pointer to pointer to char. That is, the thing it points to 
is a pointer to char.

When the function returns, endPtr will have been modified so that it now 
points to the first *unused* character of the string starting at nPtr.

Thus, if the input string is "600 rode into the valley of death", on 
return from strtod...

printf("%s\n", endPtr);

will print " rode into the valley of death"

d = strtod(nPtr, &endPtr);
if(endPtr > nPtr)
{
   you know that at least one character was converted, so you have some 
kind of valid number in d.
}

You don't have to do anything special with endPtr before the call, as 
any value it had before will be overwritten. Bear in mind that it points 
into the string starting at nPtr, so (after the call) it will only be a 
valid pointer for as long as nPtr is valid. This:

nPtr = malloc(42);
if(nPtr != NULL)
{
   d = strtod(nPtr, &endPtr);
   free(nPtr); /* nPtr is no longer valid, so neither is endPtr */
   printf("%s\n", endPtr); /* NO! */
}

is invalid code.

-- 
Richard Heathfield
Email: rjh at cpax dot org dot uk
"Usenet is a strange place" - dmr 29 July 1999
Sig line 4 vacant - apply within

[toc] | [prev] | [next] | [standalone]


#75806

FromG G <gdotone@gmail.com>
Date2015-11-11 23:42 -0800
Message-ID<909b75e4-b059-4102-982b-ac50a334161b@googlegroups.com>
In reply to#75805
On Thursday, November 12, 2015 at 2:24:29 AM UTC-5, Richard Heathfield wrote:

> endPtr is a pointer to pointer to char. That is, the thing it points to 
> is a pointer to char.
> 
> When the function returns, endPtr will have been modified so that it now 
> points to the first *unused* character of the string starting at nPtr.
> 
> Thus, if the input string is "600 rode into the valley of death", on 
> return from strtod...
> 
> printf("%s\n", endPtr);
> 
> will print " rode into the valley of death"
> 
> d = strtod(nPtr, &endPtr);
> if(endPtr > nPtr)
> {
>    you know that at least one character was converted, so you have some 
> kind of valid number in d.
> }
> 
> You don't have to do anything special with endPtr before the call, as 
> any value it had before will be overwritten. Bear in mind that it points 
> into the string starting at nPtr, so (after the call) it will only be a 
> valid pointer for as long as nPtr is valid. This:
> 
> nPtr = malloc(42);
> if(nPtr != NULL)
> {
>    d = strtod(nPtr, &endPtr);
>    free(nPtr); /* nPtr is no longer valid, so neither is endPtr */
>    printf("%s\n", endPtr); /* NO! */
> }
> 
> is invalid code.
> 

Thanks Richard.

[toc] | [prev] | [next] | [standalone]


#75837

FromKeith Thompson <kst-u@mib.org>
Date2015-11-12 08:31 -0800
Message-ID<lnk2pnqiwk.fsf@kst-u.example.com>
In reply to#75804
G G <gdotone@gmail.com> writes:
> double strtod( const char *nPtr, char **endPrt );
> (and functions like it)
>
> nPtr is a pointer to a character constant
[big snip]

nPtr is a pointer to a const (not constant) character.

A character constant is something like 'x'.  A "constant" is
a literal.  A "constant expression" is one that is evaluated at
compile time.  (It's not quite that simple, but that's close enough.)

The keyword "const" really means "read-only".  What it means here is
that you can't use the pointer nPtr to modify the character that it
points to.  The character object itself is not necessarily read-only;
you just can't use nPtr to modify it.  (Well, you can if you use a cast,
but -- don't do that.)

The "const" vs. "constant" distinction causes a lot of confusion.
Personally, I wish that "const" had been spelled "readonly".

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

[toc] | [prev] | [next] | [standalone]


#75840

Fromsupercat@casperkitty.com
Date2015-11-12 08:52 -0800
Message-ID<9dca92a6-7ff4-445b-9c40-ed3070ae8fc0@googlegroups.com>
In reply to#75837
On Thursday, November 12, 2015 at 10:31:17 AM UTC-6, Keith Thompson wrote:
> The "const" vs. "constant" distinction causes a lot of confusion.
> Personally, I wish that "const" had been spelled "readonly".

What's needed for optimization, semantically, is a distinction between
pointers whose recipient guarantees they won't be used to modify an object,
period, versus those that won't be used to modify an object *outside the
control of whoever supplied the pointer*.  For example, given:

    void wowzo(char ch)
    {
      char foo[] = "123 ABC";
      char *p;
      foo[3] = ch;
      strtod(foo, &p);
      if (foo[4] == 'A')
      {
        p[0]++;
        if (foo[4] == 'A') printf("Hey!");
      }
    }

a compiler which didn't know the precise workings of strtod would have no
way of knowing whether p[0]++ could increment foo[4].  Even if the prototype
of strtod is interpreted as recognizing that it won't cause "foo" to be
modified outside the control of the code above, it the compiler has no way
of knowing whether the code above might be expecting to have the write to
p[0] modify foo[4].

[toc] | [prev] | [next] | [standalone]


#75846

FromG G <gdotone@gmail.com>
Date2015-11-12 09:43 -0800
Message-ID<6b8eee47-6184-45f2-8b56-b0e51c16a763@googlegroups.com>
In reply to#75837
On Thursday, November 12, 2015 at 11:31:17 AM UTC-5, Keith Thompson wrote:
 
> nPtr is a pointer to a const (not constant) character.
> 
> A character constant is something like 'x'.  A "constant" is
> a literal.  A "constant expression" is one that is evaluated at
> compile time.  (It's not quite that simple, but that's close enough.)
> 
> The keyword "const" really means "read-only".  What it means here is
> that you can't use the pointer nPtr to modify the character that it
> points to.  The character object itself is not necessarily read-only;
> you just can't use nPtr to modify it.  (Well, you can if you use a cast,
> but -- don't do that.)
> 

> The "const" vs. "constant" distinction causes a lot of confusion.
> Personally, I wish that "const" had been spelled "readonly".

Thanks Keith, my problem, I think stems from the appendix A.2.5.2 in
C by Kernighan and Ritchie.

A character constant is a sequence of one or more characters 
enclosed in single quotes as in 'x'. The value of a character 
constant with only one character is the numeric value of the 
character inthe machine's character set at execution time. 
The value of a multi-character constant is implementation-defined.

A string literal, also called a string constant, is a sequence 
of characters surrounded by double quotes as in "...". A string 
has type ``array of characters'' and storage class static 
(see Par.A.3 below) and is initialized with the given characters.

It's stuck in my mind, try and shake it.

const char* nPtr can point to either one of these two types?

[toc] | [prev] | [next] | [standalone]


#75849

FromRichard Heathfield <rjh@cpax.org.uk>
Date2015-11-12 17:59 +0000
Message-ID<n22jue$ui1$1@dont-email.me>
In reply to#75846
On 12/11/15 17:43, G G wrote:
> On Thursday, November 12, 2015 at 11:31:17 AM UTC-5, Keith Thompson wrote:
>
>> nPtr is a pointer to a const (not constant) character.
>>
>> A character constant is something like 'x'.  A "constant" is
>> a literal.  A "constant expression" is one that is evaluated at
>> compile time.  (It's not quite that simple, but that's close enough.)
>>
>> The keyword "const" really means "read-only".  What it means here is
>> that you can't use the pointer nPtr to modify the character that it
>> points to.  The character object itself is not necessarily read-only;
>> you just can't use nPtr to modify it.  (Well, you can if you use a cast,
>> but -- don't do that.)
>>
>
>> The "const" vs. "constant" distinction causes a lot of confusion.
>> Personally, I wish that "const" had been spelled "readonly".
>
> Thanks Keith, my problem, I think stems from the appendix A.2.5.2 in
> C by Kernighan and Ritchie.
>
> A character constant is a sequence of one or more characters
> enclosed in single quotes as in 'x'. The value of a character
> constant with only one character is the numeric value of the
> character inthe machine's character set at execution time.
> The value of a multi-character constant is implementation-defined.
>
> A string literal, also called a string constant, is a sequence
> of characters surrounded by double quotes as in "...". A string
> has type ``array of characters'' and storage class static
> (see Par.A.3 below) and is initialized with the given characters.
>
> It's stuck in my mind, try and shake it.
>
> const char* nPtr can point to either one of these two types?


Ah, I see.

The answer is "no, but I can see why you think so". To keep things 
simple for the time being, though, let's leave the const out of it. The 
const is a safety feature which, although important, may be distracting 
you a little, so let's just ignore it for now, and come back to it.

A char * (that is, a pointer to char) can only point at one individual char.

*Nevertheless*, there is no reason why that char cannot be the first in 
a contiguous ("without a break") series of chars laid out in one long 
line in memory. Knowing the address of the first, it is easy to 
calculate the address of the second, the third, and so on.

Since a string is only a contiguous series of char terminated by the 
first null character, we can point to the first element of a string (we 
are often lazy and say 'pointer to string' when we really mean 'pointer 
to the first character in a string'), and we can then access the whole 
string because the other characters in it are in the obvious places. 
Hence the canonical coding of strcpy as while(*s++=*t++){}, for example.

I hope that's clearer now.

The const modifier to char *nPtr is a separate issue. It only means 
"can't change the string's value through this pointer". This is helpful 
because it prevents (or, to be more precise, makes it considerably more 
difficult to fall prey to) accidental modification. Although it /is/ 
possible to change a const-qualified object's value, you have to work at 
it pretty hard, and the C Standard is looking over your shoulder the 
whole time saying, "nope... nope... nope... bad idea... nope..." to 
everything you try, until eventually you want to punch it on the nose.

-- 
Richard Heathfield
Email: rjh at cpax dot org dot uk
"Usenet is a strange place" - dmr 29 July 1999
Sig line 4 vacant - apply within

[toc] | [prev] | [next] | [standalone]


#75851

FromEric Sosman <esosman@comcast-dot-net.invalid>
Date2015-11-12 13:10 -0500
Message-ID<n22kj1$1h6$1@dont-email.me>
In reply to#75846
On 11/12/2015 12:43 PM, G G wrote:
> [...]
> Thanks Keith, my problem, I think stems from the appendix A.2.5.2 in
> C by Kernighan and Ritchie.
>
> A character constant is a sequence of one or more characters
> enclosed in single quotes as in 'x'. The value of a character
> constant with only one character is the numeric value of the
> character inthe machine's character set at execution time.
> The value of a multi-character constant is implementation-defined.
>
> A string literal, also called a string constant, is a sequence
> of characters surrounded by double quotes as in "...". A string
> has type ``array of characters'' and storage class static
> (see Par.A.3 below) and is initialized with the given characters.
>
> It's stuck in my mind, try and shake it.
>
> const char* nPtr can point to either one of these two types?

     Sort of.  A pointer-to-char can point at any char, whether
that char is part of a string or is not.  When used as the first
argument to strtod() it must point to a char that is part of a
string.

     Perhaps your confusion arises from thinking of a string as
a "type."  It isn't, really: There is no "string type" in C.
A string is just a sequence of char values, formatted according
to a special convention: The "value" or "payload" consists of
the first group of char values, then comes a '\0' char value
that marks the end of the payload, and if any additional char
values follow the '\0' they are ignored.  If the first group is
of zero length (that is, the very first char value is '\0'), the
string's value is empty.

     The C compiler understands this convention, and when it
encounters a string literal like "xyz" in the source it will
automatically generate an array something like

	char s[4] = {'x', 'y', 'z', '\0'}

... and will supply a pointer to s[0] whenever "xyz" shows up.
(There are a few exceptions that need not concern and confuse
you just yet; this treatment is by far the commonest.)

-- 
esosman@comcast-dot-net.invalid
"Don't be afraid of work. Make work afraid of you." -- TLM

[toc] | [prev] | [next] | [standalone]


#75854

FromJames Kuyper <jameskuyper@verizon.net>
Date2015-11-12 13:19 -0500
Message-ID<n22l32$43t$1@dont-email.me>
In reply to#75846
On 11/12/2015 12:43 PM, G G wrote:
> On Thursday, November 12, 2015 at 11:31:17 AM UTC-5, Keith Thompson wrote:
>  
>> nPtr is a pointer to a const (not constant) character.
>>
>> A character constant is something like 'x'.  A "constant" is
>> a literal.  A "constant expression" is one that is evaluated at
>> compile time.  (It's not quite that simple, but that's close enough.)
>>
>> The keyword "const" really means "read-only".  What it means here is
>> that you can't use the pointer nPtr to modify the character that it
>> points to.  The character object itself is not necessarily read-only;
>> you just can't use nPtr to modify it.  (Well, you can if you use a cast,
>> but -- don't do that.)
>>
> 
>> The "const" vs. "constant" distinction causes a lot of confusion.
>> Personally, I wish that "const" had been spelled "readonly".
> 
> Thanks Keith, my problem, I think stems from the appendix A.2.5.2 in
> C by Kernighan and Ritchie.
> 
> A character constant is a sequence of one or more characters 
> enclosed in single quotes as in 'x'. The value of a character 
> constant with only one character is the numeric value of the 
> character inthe machine's character set at execution time. 
> The value of a multi-character constant is implementation-defined.
> 
> A string literal, also called a string constant, is a sequence 
> of characters surrounded by double quotes as in "...". A string 
> has type ``array of characters'' and storage class static 
> (see Par.A.3 below) and is initialized with the given characters.
> 
> It's stuck in my mind, try and shake it.
> 
> const char* nPtr can point to either one of these two types?

THe word constant that appears in those paragraphs has nothing
whatsoever to do with the keyword 'const', so you should try to get that
idea unstuck from head and "shake it out, shake it out...". To show that
there's no relation, I'll use some character and string constants in the
following explanation of 'const' - but you should see that the fact that
they are constants is irrelevant to that explanation.

'C' is a character constant. No storage needs to be is set aside for
character constants, any more than storage needs to be set aside for 3.
Therefore, it's not possible to point at a character constant, just as
it's not possible to point at, for instance, 3.14.

Something you can do is store the value of a character constant in a
variable. Storage is reserved for the variable, and nPtr can therefore
point at it:

    char var = 'C';
    nPtr = &var;

This exactly parallel to
    double pi = 3.141592653;
    double *pd = &pi;

    pd = &3.141592653;	// Constraint violation
    nPtr = &'C';	// Constraint violation

"string literal" is a string literal. If used anywhere other than as the
initializer of an array, it causes the creation of an unnamed array of
char, initialized with the elements of that string literal, plus a
terminating null character (technically, it also causes the creation of
such an array even when used as an initializer - but there's no way a
strictly conforming program can make use of that fact, so that array
need not actually exist). In most contexts, lvalues of array type
automatically get converted into pointers to the first element of the
array. Therefore,

    nPtr = "string literal";

is functionally equivalent to

    char _unnamed_array[15] = {'s', 't', 'r', 'i', 'n', 'g', ' ',
        'l', 'i', 't', 'e', 'r', 'a', 'l', '\0'}
    nPtr = _unnamed_array;

So far, Nothing I've said had ANYTHING to do with the 'const' in the
declaration of nPtr. In order to demonstrate what that the const keyword
means, I'll first have to introduce a couple of variables whose
definition is declared 'const':

    const char const_var = 'V';
    const char const_array[] = "Hello world!";

'const' used in this way means that any attempt to modify the value of
either of those objects has undefined behavior.  Now, nPtr can also
point at these objects:

    nPtr = &const_var;
    nPtr = const_array;

So what difference does it make? If a declaration says 'const *' (NOT
'*const', which has a different meaning), what it means is that the
thing it points at is allowed (but not required) to be const-qualified.
To make this clearer, lets see what happens if we leave that 'const' out:

    char *pointer;
    pointer = &var;
    pointer = "string literal";

So far, so good - no difference from nPtr. Here's the difference:

    pointer = &const_var; 	// constraint violation
    pointer = const_array;	// constraint violation

The reason for this rule is simple:

    *pointer = 'A';
    *nPtr = 'a';	// constraint violation

Since 'pointer' can be used to modify the object it points at, you're
not allowed to set 'pointer' to point at something declared const.
Because nPtr cannot be used to modify the object it points at, it's
perfectly safe to point it at something declared const.
-- 
James Kuyper

[toc] | [prev] | [next] | [standalone]


#75868

FromKeith Thompson <kst-u@mib.org>
Date2015-11-12 11:32 -0800
Message-ID<ln7flnqahi.fsf@kst-u.example.com>
In reply to#75846
G G <gdotone@gmail.com> writes:
> On Thursday, November 12, 2015 at 11:31:17 AM UTC-5, Keith Thompson wrote:
>> nPtr is a pointer to a const (not constant) character.
>> 
>> A character constant is something like 'x'.  A "constant" is
>> a literal.  A "constant expression" is one that is evaluated at
>> compile time.  (It's not quite that simple, but that's close enough.)
>> 
>> The keyword "const" really means "read-only".  What it means here is
>> that you can't use the pointer nPtr to modify the character that it
>> points to.  The character object itself is not necessarily read-only;
>> you just can't use nPtr to modify it.  (Well, you can if you use a cast,
>> but -- don't do that.)
>
>> The "const" vs. "constant" distinction causes a lot of confusion.
>> Personally, I wish that "const" had been spelled "readonly".
>
> Thanks Keith, my problem, I think stems from the appendix A.2.5.2 in
> C by Kernighan and Ritchie.
>
> A character constant is a sequence of one or more characters 
> enclosed in single quotes as in 'x'. The value of a character 
> constant with only one character is the numeric value of the 
> character inthe machine's character set at execution time. 
> The value of a multi-character constant is implementation-defined.
>
> A string literal, also called a string constant, is a sequence 
> of characters surrounded by double quotes as in "...". A string 
> has type ``array of characters'' and storage class static 
> (see Par.A.3 below) and is initialized with the given characters.
>
> It's stuck in my mind, try and shake it.

That quote from K&R is perfectly accurate; there's nothing to "shake".

The point is that K&R are talking about *constants*, which are lexical
entities that can appear in C source code.  The quoted passage has
doesn't mention the "const" qualifier, and has very little to do with
it.

> const char* nPtr can point to either one of these two types?

Given a declaration
    const char *nPtr;
nPtr points to an object of type char.  (Or it might be a null
pointer that doesn't point to anything, or it might have a garbage
value.)  The "const" places a restriction on the use of the pointer;
you can't use the pointer to modify the object it points to.
It's a safety net, a way to ask the compiler not to let you do
something that might be dangerous.

It can't point to a character constant, because there's no such thing as
a character constant *in a running program*.  'x' is a character
constant, but it exists in that form *only* as a sequence of 3
characters in your ".c" file.  There is no run-time object associated
with it.  Similarly, a pointer of type int* can't point to 42 -- though
it can point to an int object in which you've stored the value 42.

A string literal, unlike a character or integer constant, does cause the
creation of an object at run time.  A char* pointer *can* point to an
element of that object.  (And for safety, such a pointer should be
declared as "const char*", because you want to avoid trying to modify
the contents of the array created by the string literal.)

I hope I haven't caused more confusion.  Please feel free to follow up
if you don't understand what I've written (or set it aside and come back
to it later if you prefer).

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

[toc] | [prev] | [next] | [standalone]


#75872

Fromsupercat@casperkitty.com
Date2015-11-12 12:17 -0800
Message-ID<c866d654-7f88-4036-812a-097405478809@googlegroups.com>
In reply to#75868
On Thursday, November 12, 2015 at 1:33:08 PM UTC-6, Keith Thompson wrote:
> A string literal, unlike a character or integer constant, does cause the
> creation of an object at run time.  A char* pointer *can* point to an
> element of that object.  (And for safety, such a pointer should be
> declared as "const char*", because you want to avoid trying to modify
> the contents of the array created by the string literal.)

While I don't think anything would forbid an implementation where string
literals could create objects at run time, I would suggest that they more
often create objects at compile time which are aggregated into an object
which gets created at load time.  String literal expressions then identify
pieces of that object.

[toc] | [prev] | [next] | [standalone]


#75877

FromKeith Thompson <kst-u@mib.org>
Date2015-11-12 12:48 -0800
Message-ID<lny4e3osfs.fsf@kst-u.example.com>
In reply to#75872
supercat@casperkitty.com writes:
> On Thursday, November 12, 2015 at 1:33:08 PM UTC-6, Keith Thompson wrote:
>> A string literal, unlike a character or integer constant, does cause the
>> creation of an object at run time.  A char* pointer *can* point to an
>> element of that object.  (And for safety, such a pointer should be
>> declared as "const char*", because you want to avoid trying to modify
>> the contents of the array created by the string literal.)
>
> While I don't think anything would forbid an implementation where string
> literals could create objects at run time, I would suggest that they more
> often create objects at compile time which are aggregated into an object
> which gets created at load time.  String literal expressions then identify
> pieces of that object.

Objects don't exist at compile time.

A compiler doesn't create an object.  It generates code that results in
the creation of an object when that code is executed.

When a C compiler encounters a string literal, it generates code that,
when executed, will result in the runtime creation of an array object
that will hold the specified sequence of values.  That creation
logically occurs some time after the program starts executing but before
entry to main().

Typically it might occur as the operating system is loading
the executable (so there might not actually be a sequence of
CPU instructions in the executable that causes the object to be
created), and the object might be bundled with other static objects,
but those are implementation details.

All this is subject to optimization; an object that's never referenced
might not be created.

So, in my source code I have:

    const char *s = "hello";

At run time, there exists a static object of type char[6] containing
the characters { 'h', 'e', 'l', 'l', 'o', '\0' }.  After the flow
of execution reaches the declaratio nof s, it is initialized to
point to the element containing the 'h'.

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

[toc] | [prev] | [next] | [standalone]


#75881

Fromsupercat@casperkitty.com
Date2015-11-12 13:39 -0800
Message-ID<8bbcc376-a820-4308-b8f2-90bcf4fa13e2@googlegroups.com>
In reply to#75877
On Thursday, November 12, 2015 at 2:48:23 PM UTC-6, Keith Thompson wrote:
> A compiler doesn't create an object.  It generates code that results in
> the creation of an object when that code is executed.

I've seen a number of compilers where a file containing:

    char *getmsg(int n) { return n ? "Yep" : "Nope"; }

will get turned into something closer to:

    static unsinged char __static_data[9] =
      {'Y','e','p',0, 'N','o','p','e', 0};
    char *getmsg(int n) { return n ? __static_data+0, 
                                     __static_data+4; }

So from the point of view of the linker there is for each compilation unit
only one blob holding all the static data from that unit, rather than a
separate blob for each string literal.  Only from the point of view of the
compiler is "Nope\0" a distinct object.

Otherwise, my main point was that saying object is created "at runtime" would
in most contexts imply that it was created at the point where the string
literal was used in the code.  That is true of some BASIC interpreters, but
is not true of typical C implementations.

[toc] | [prev] | [next] | [standalone]


#75892

Fromglen herrmannsfeldt <gah@ugcs.caltech.edu>
Date2015-11-12 23:24 +0000
Message-ID<n23735$dsc$1@speranza.aioe.org>
In reply to#75881
supercat@casperkitty.com wrote:
> On Thursday, November 12, 2015 at 2:48:23 PM UTC-6, Keith Thompson wrote:
>> A compiler doesn't create an object.  It generates code that results in
>> the creation of an object when that code is executed.
 
> I've seen a number of compilers where a file containing:
 
>    char *getmsg(int n) { return n ? "Yep" : "Nope"; }
 
> will get turned into something closer to:
 
>    static unsinged char __static_data[9] =
>      {'Y','e','p',0, 'N','o','p','e', 0};
>    char *getmsg(int n) { return n ? __static_data+0, 
>                                     __static_data+4; }
 
> So from the point of view of the linker there is for each compilation unit
> only one blob holding all the static data from that unit, rather than a
> separate blob for each string literal.  Only from the point of view of the
> compiler is "Nope\0" a distinct object.

In the systems that I know in enough detail, you can't separate them.
Bytes go into the object program, and instructions have a way to
address them.  If two objects are adjacent, they are in consecutive
bytes.

Now, for OS/360 (and successor) object programs, there can be holes
which aren't initialized. 

    DC C'YEP',X'O0'
    DC C'NOPE',X'O0'

would assemble without holes, but

    DC C'YEP',X'O0'
    DS CL10
    DC C'NOPE',X'O0'

would assemble with a 10 byte hole in between. The two constants
would come out on separate object program records.  They are
then filled in either at link time, or still holes at program fetch.

(It might be that OS/360 didn't clear memory before loading programs,
but I suspect newer systems do.)

-- glen

 

[toc] | [prev] | [next] | [standalone]


#75907

FromKeith Thompson <kst-u@mib.org>
Date2015-11-12 17:14 -0800
Message-ID<lnegfupunk.fsf@kst-u.example.com>
In reply to#75881
supercat@casperkitty.com writes:
> On Thursday, November 12, 2015 at 2:48:23 PM UTC-6, Keith Thompson wrote:
>> A compiler doesn't create an object.  It generates code that results in
>> the creation of an object when that code is executed.
>
> I've seen a number of compilers where a file containing:
>
>     char *getmsg(int n) { return n ? "Yep" : "Nope"; }
>
> will get turned into something closer to:
>
>     static unsinged char __static_data[9] =
>       {'Y','e','p',0, 'N','o','p','e', 0};
>     char *getmsg(int n) { return n ? __static_data+0, 
>                                      __static_data+4; }
>
> So from the point of view of the linker there is for each compilation
> unit only one blob holding all the static data from that unit, rather
> than a separate blob for each string literal.  Only from the point of
> view of the compiler is "Nope\0" a distinct object.

From the point of view of the C language, the anonymous array containing
"Nope\0" is a distinct object.  Distinct objects can easily be adjacent
in memory.  But the object does not exist until after you execute the
program.

> Otherwise, my main point was that saying object is created "at
> runtime" would in most contexts imply that it was created at the point
> where the string literal was used in the code.  That is true of some
> BASIC interpreters, but is not true of typical C implementations.

But that's not what I said.  The array object has static storage
duration, so it's allocated during program startup (before main is
entered) and remains allocated until the program terminates.  That's
still run time.

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

[toc] | [prev] | [next] | [standalone]


#75909

Fromsupercat@casperkitty.com
Date2015-11-12 17:42 -0800
Message-ID<d32a5742-66b1-4ba1-a8a7-89db7ab4c397@googlegroups.com>
In reply to#75907
On Thursday, November 12, 2015 at 7:15:01 PM UTC-6, Keith Thompson wrote:
> But that's not what I said.  The array object has static storage
> duration, so it's allocated during program startup (before main is
> entered) and remains allocated until the program terminates.  That's
> still run time.

For systems which use non-relocatable code images, allocation occurs at link
time.  In many embedded systems, strings will be stored in some kind of ROM
before a program starts (in my younger days, I'd use a device to store code
and data into ROM chips before installing those chips in the target system).
What exactly is supposed to happen at runtime to create an object from a
string which was stored in ROM before the CPU was powered on and will be
accessed directly from there?

[toc] | [prev] | [next] | [standalone]


#75914

FromKeith Thompson <kst-u@mib.org>
Date2015-11-12 18:20 -0800
Message-ID<ln37waprmt.fsf@kst-u.example.com>
In reply to#75909
supercat@casperkitty.com writes:
> On Thursday, November 12, 2015 at 7:15:01 PM UTC-6, Keith Thompson wrote:
>> But that's not what I said.  The array object has static storage
>> duration, so it's allocated during program startup (before main is
>> entered) and remains allocated until the program terminates.  That's
>> still run time.
>
> For systems which use non-relocatable code images, allocation occurs
> at link time.  In many embedded systems, strings will be stored in
> some kind of ROM before a program starts (in my younger days, I'd use
> a device to store code and data into ROM chips before installing those
> chips in the target system).  What exactly is supposed to happen at
> runtime to create an object from a string which was stored in ROM
> before the CPU was powered on and will be accessed directly from
> there?

What happens at run time is that the relevant chunk of ROM logically
changes from being just a chunk of ROM to being a C object accessible to
a running C program.

In the absence of a running C program, it's not an "object" in the sense
used by the C standard.  An "object" is a "region of data storage in the
execution environment, the contents of which can represent values";
until the program starts, there is no execution environment.

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

[toc] | [prev] | [next] | [standalone]


#75891

Fromglen herrmannsfeldt <gah@ugcs.caltech.edu>
Date2015-11-12 23:15 +0000
Message-ID<n236ih$cvg$1@speranza.aioe.org>
In reply to#75877
Keith Thompson <kst-u@mib.org> wrote:
> supercat@casperkitty.com writes:
(snip)
>> While I don't think anything would forbid an implementation where string
>> literals could create objects at run time, I would suggest that they more
>> often create objects at compile time which are aggregated into an object
>> which gets created at load time.  String literal expressions then identify
>> pieces of that object.
 
> Objects don't exist at compile time.

I suspect it isn't part of the C standard, but most systems create
static objects at compile time. They exist in the object module,
and resultant load module.  
 
> A compiler doesn't create an object.  It generates code that results in
> the creation of an object when that code is executed.

C conveniently makes it hard to create large static objects initialized
to other than zero. Many object module and load module forms have
optmizations for static zero, but not all.

If you compile a nice small Fortran program like:

      INTEGER :: X(1000000)=2
      PRINT *,X(1234)
      END

on most systems, including unix-like systems, all 1000000 twos
are generated at compile time and written to the object module.

> When a C compiler encounters a string literal, it generates code that,
> when executed, will result in the runtime creation of an array object
> that will hold the specified sequence of values.  That creation
> logically occurs some time after the program starts executing but before
> entry to main().

On all systems I know of, they are generated at compile time,
written to the object module, then load module, loaded into memory
when it is read in, and before any instructions are executed.

But yes, as far as I know the standard allows other things to happen
between the first executed instruction and entry to main().
 
> Typically it might occur as the operating system is loading
> the executable (so there might not actually be a sequence of
> CPU instructions in the executable that causes the object to be
> created), and the object might be bundled with other static objects,
> but those are implementation details.

Even more, they might be loaded by I/O hardware, such that no CPU
instructions are involved, but yes, implementation details.
 
> All this is subject to optimization; an object that's never referenced
> might not be created.

Note that the above Fortran program fills the whole array, even 
though only one element is needed.  (I have seen the files.)
 
> So, in my source code I have:
 
>    const char *s = "hello";
 
> At run time, there exists a static object of type char[6] containing
> the characters { 'h', 'e', 'l', 'l', 'o', '\0' }.  After the flow
> of execution reaches the declaratio nof s, it is initialized to
> point to the element containing the 'h'.

I suppose in theory, it doesn't have to point to the element
containing 'h' until just before it is used, and if never used,
the constant could be optimized away. 

In the case of a large static object with low entropy, the program
could create it at run time just before it is needed.  I don't
know of any that do it, though.

-- glen

[toc] | [prev] | [next] | [standalone]


#75893

FromEric Sosman <esosman@comcast-dot-net.invalid>
Date2015-11-12 18:30 -0500
Message-ID<n237a0$kcb$1@dont-email.me>
In reply to#75891
On 11/12/2015 6:15 PM, glen herrmannsfeldt wrote:
> Keith Thompson <kst-u@mib.org> wrote:
>> supercat@casperkitty.com writes:
> (snip)
>>> While I don't think anything would forbid an implementation where string
>>> literals could create objects at run time, I would suggest that they more
>>> often create objects at compile time which are aggregated into an object
>>> which gets created at load time.  String literal expressions then identify
>>> pieces of that object.
>
>> Objects don't exist at compile time.
>
> I suspect it isn't part of the C standard, but most systems create
> static objects at compile time. They exist in the object module,
> and resultant load module.

     I think Keith's point is that the contents of the "object module"
and "load module" are not objects until run time; they're just
instructions to the starter-upper to create some objects before
calling main().

>> A compiler doesn't create an object.  It generates code that results in
>> the creation of an object when that code is executed.
>
> C conveniently makes it hard to create large static objects initialized
> to other than zero. Many object module and load module forms have
> optmizations for static zero, but not all.

     ... which seems to support Keith's view.  You write source code
for a big zero object like `static char array[10000];', but you may
search in vain for a 10000-byte thingumabob in the products of the
compiler and linker.  There's a good chance you'll just find a little
notation somewhere that says "Dear run-time: Please set aside 42KB of
pre-zeroed bytes (maybe called bss), and I'll treat bytes X through
X+9999 of that region as `array'." If that sort of thing happens, it's
pretty clear that the object has not been created prior to run-time.

-- 
esosman@comcast-dot-net.invalid
"Don't be afraid of work. Make work afraid of you." -- TLM

[toc] | [prev] | [next] | [standalone]


#75902

Fromsupercat@casperkitty.com
Date2015-11-12 16:47 -0800
Message-ID<066a9276-ff53-4bd9-8572-5ae27e56e1ab@googlegroups.com>
In reply to#75893
On Thursday, November 12, 2015 at 5:30:27 PM UTC-6, Eric Sosman wrote:
>      ... which seems to support Keith's view.  You write source code
> for a big zero object like `static char array[10000];', but you may
> search in vain for a 10000-byte thingumabob in the products of the
> compiler and linker.  There's a good chance you'll just find a little
> notation somewhere that says "Dear run-time: Please set aside 42KB of
> pre-zeroed bytes (maybe called bss), and I'll treat bytes X through
> X+9999 of that region as `array'." If that sort of thing happens, it's
> pretty clear that the object has not been created prior to run-time.

If the linker generates non-relocatable code image, storage for all static
objects will be allocated at that time.  If the loader stores code and
data as it is read from the storage medium, most static objects will be
fully initialized even before the program has finished loading (if a
static object contains lots of zero space, that space might be omitted
from the file but cleared by startup code).  Even there, however, the
objects would exist even before code cleared them out.

If you want to push things a little further, consider embedded systems.
In many cases, code and data will get written into an EPROM chip which is
sitting in a device programming machine entirely separate from the main
CPU and then plugged into the CPU board to use them.  The target system
CPU will do *nothing* to create the objects--they'll exist the moment it's
powered on for the first time with the chips installed.

[toc] | [prev] | [next] | [standalone]


Page 1 of 2  [1] 2  Next page →

Back to top | Article view | comp.lang.c


csiph-web