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


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

sizeof environment variables array = 1?

Started byDFS <nospam@dfs.com>
First post2017-06-08 11:13 -0400
Last post2017-06-08 11:51 -0700
Articles 20 on this page of 41 — 15 participants

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


Contents

  sizeof environment variables array = 1? DFS <nospam@dfs.com> - 2017-06-08 11:13 -0400
    Re: sizeof environment variables array = 1? Lew Pitcher <lew.pitcher@digitalfreehold.ca> - 2017-06-08 11:25 -0400
      Re: sizeof environment variables array = 1? Keith Thompson <kst-u@mib.org> - 2017-06-08 09:34 -0700
        Re: sizeof environment variables array = 1? DFS <nospam@dfs.com> - 2017-06-08 13:14 -0400
          Re: sizeof environment variables array = 1? jameskuyper@verizon.net - 2017-06-08 10:51 -0700
    Re: sizeof environment variables array = 1? Gareth Owen <gwowen@gmail.com> - 2017-06-08 16:56 +0100
      Re: sizeof environment variables array = 1? DFS <nospam@dfs.com> - 2017-06-08 12:18 -0400
        Re: sizeof environment variables array = 1? scott@slp53.sl.home (Scott Lurndal) - 2017-06-08 16:35 +0000
        Re: sizeof environment variables array = 1? Lew Pitcher <lew.pitcher@digitalfreehold.ca> - 2017-06-08 12:43 -0400
          Re: sizeof environment variables array = 1? DFS <nospam@dfs.com> - 2017-06-08 13:49 -0400
            Re: sizeof environment variables array = 1? "James R. Kuyper" <jameskuyper@verizon.net> - 2017-06-08 13:58 -0400
              Re: sizeof environment variables array = 1? DFS <nospam@dfs.com> - 2017-06-08 14:45 -0400
            Re: sizeof environment variables array = 1? Keith Thompson <kst-u@mib.org> - 2017-06-08 12:10 -0700
              Re: sizeof environment variables array = 1? DFS <nospam@dfs.com> - 2017-06-09 11:21 -0400
              Re: sizeof environment variables array = 1? Richard Heathfield <rjh@cpax.org.uk> - 2017-06-09 16:23 +0100
                Re: sizeof environment variables array = 1? "James R. Kuyper" <jameskuyper@verizon.net> - 2017-06-09 11:48 -0400
                  Re: sizeof environment variables array = 1? Richard Heathfield <rjh@cpax.org.uk> - 2017-06-09 16:53 +0100
                    Re: sizeof environment variables array = 1? "James R. Kuyper" <jameskuyper@verizon.net> - 2017-06-09 12:18 -0400
                      Re: sizeof environment variables array = 1? Richard Heathfield <rjh@cpax.org.uk> - 2017-06-09 17:28 +0100
                  Re: sizeof environment variables array = 1? Keith Thompson <kst-u@mib.org> - 2017-06-09 09:12 -0700
                Re: sizeof environment variables array = 1? "Patrick.Schluter" <Patrick.Schluter@free.fr> - 2017-06-10 09:28 +0200
            Re: sizeof environment variables array = 1? jak <please@nospam.tnx> - 2017-06-08 22:18 +0200
              Re: sizeof environment variables array = 1? DFS <nospam@dfs.com> - 2017-06-08 17:31 -0400
                Re: sizeof environment variables array = 1? Keith Thompson <kst-u@mib.org> - 2017-06-08 15:12 -0700
                  Re: sizeof environment variables array = 1? DFS <nospam@dfs.com> - 2017-06-09 11:21 -0400
                    Re: sizeof environment variables array = 1? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2017-06-09 16:39 +0100
                      Re: sizeof environment variables array = 1? Gareth Owen <gwowen@gmail.com> - 2017-06-10 07:26 +0100
                        Re: sizeof environment variables array = 1? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2017-06-10 13:21 +0100
                      Re: sizeof environment variables array = 1? gordonb.q80bx@burditt.org (Gordon Burditt) - 2017-06-10 17:32 -0500
                        Re: sizeof environment variables array = 1? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2017-06-11 01:01 +0100
                        Re: sizeof environment variables array = 1? luser droog <luser.droog@gmail.com> - 2017-06-11 01:28 -0700
                        Re: sizeof environment variables array = 1? raltbos@xs4all.nl (Richard Bos) - 2017-06-17 18:38 +0000
                    Re: sizeof environment variables array = 1? Keith Thompson <kst-u@mib.org> - 2017-06-09 08:41 -0700
                    Re: sizeof environment variables array = 1? "James R. Kuyper" <jameskuyper@verizon.net> - 2017-06-09 11:50 -0400
                    Re: sizeof environment variables array = 1? raltbos@xs4all.nl (Richard Bos) - 2017-06-17 18:37 +0000
                      Re: sizeof environment variables array = 1? DFS <nospam@dfs.com> - 2017-06-18 09:11 -0400
            Re: sizeof environment variables array = 1? "Patrick.Schluter" <Patrick.Schluter@free.fr> - 2017-06-10 09:19 +0200
        Re: sizeof environment variables array = 1? Robert Wessel <robertwessel2@yahoo.com> - 2017-06-08 12:44 -0500
      Re: sizeof environment variables array = 1? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2017-06-08 18:01 +0100
        Re: sizeof environment variables array = 1? Gareth Owen <gwowen@gmail.com> - 2017-06-08 18:45 +0100
      Re: sizeof environment variables array = 1? Keith Thompson <kst-u@mib.org> - 2017-06-08 11:51 -0700

Page 1 of 3  [1] 2 3  Next page →


#111820 — sizeof environment variables array = 1?

FromDFS <nospam@dfs.com>
Date2017-06-08 11:13 -0400
Subjectsizeof environment variables array = 1?
Message-ID<ohbpd7$5r3$2@dont-email.me>
int main(int argc, char *argv[], char *env[])
{
   printf("%d\n",sizeof(env)/sizeof(env[0]));
   return(0);
)

Output is 1.

Why?


If I add:

while (*env) {printf("%s\n", *env++);}

it prints out all 65 of them.

[toc] | [next] | [standalone]


#111822

FromLew Pitcher <lew.pitcher@digitalfreehold.ca>
Date2017-06-08 11:25 -0400
Message-ID<ohbq3c$6oj$1@dont-email.me>
In reply to#111820
DFS wrote:

> int main(int argc, char *argv[], char *env[])
> {
>    printf("%d\n",sizeof(env)/sizeof(env[0]));
>    return(0);
> )
> 
> Output is 1.
> 
> Why?

Given
  char *env[];
then
  env is a pointer (to a pointer to char)
and
  env[0] is also a pointer (to a char)

Apparently, in your execution environment,
a >>pointer to a pointer to char<< is the same size as a >>pointer to char<<
and, thus, division of the size of one by the size of the other gives a 
value of 1

> 
> If I add:
> 
> while (*env) {printf("%s\n", *env++);}
> 
> it prints out all 65 of them.


-- 
Lew Pitcher
"In Skills, We Trust"
PGP public key available upon request

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


#111832

FromKeith Thompson <kst-u@mib.org>
Date2017-06-08 09:34 -0700
Message-ID<lnvao6igkb.fsf@kst-u.example.com>
In reply to#111822
Lew Pitcher <lew.pitcher@digitalfreehold.ca> writes:
> DFS wrote:
>> int main(int argc, char *argv[], char *env[])
>> {
>>    printf("%d\n",sizeof(env)/sizeof(env[0]));

Should be "%zu\n", not "%d\n" -- or you could use "%d\n" and cast the
argument to int.

>>    return(0);
>> )
>> 
>> Output is 1.
>> 
>> Why?
>
> Given
>   char *env[];
> then
>   env is a pointer (to a pointer to char)
> and
>   env[0] is also a pointer (to a char)

`char *env[]` normally makes env an array of char* pointers, but because
it's a parameter declaration it's "adjusted" to become a pointer.

This:
    int main(int argc, char *argv[], char *env[])
is exactly equivalent to this:
    int main(int argc, char **argv, char **env)

Given a pointer to the initial element of an array, you can't
use sizeof to determine the number of elements in that array.
You can traverse the array elements to find the length *if* there's
a consistent convention marking the end of the array (typically a
null pointer for an array of pointers, or a null character for an
array of characters).

Incidentally, this declaration of main is not portable, but an
optional third "env" parameter is a common extension.

> Apparently, in your execution environment,
> a >>pointer to a pointer to char<< is the same size as a >>pointer to char<<
> and, thus, division of the size of one by the size of the other gives a 
> value of 1

In principle, it could still yield 1 if, for example, sizeof (char**)
== 6 and sizeof (char*) == 4.  But that detail in understanding
the semantics of this semantically incorrect code is less important
than fixing the code.

>> If I add:
>> 
>> while (*env) {printf("%s\n", *env++);}
>> 
>> it prints out all 65 of them.

Because it scans for the null pointer that conventionally marks the end
of the array.  If the program were invoked with an `env` data structure
that isn't properly terminated, you'd have undefined behavior.

-- 
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]


#111842

FromDFS <nospam@dfs.com>
Date2017-06-08 13:14 -0400
Message-ID<ohc0fl$vcl$3@dont-email.me>
In reply to#111832
On 6/8/2017 12:34 PM, Keith Thompson wrote:
> Lew Pitcher <lew.pitcher@digitalfreehold.ca> writes:
>> DFS wrote:
>>> int main(int argc, char *argv[], char *env[])
>>> {
>>>     printf("%d\n",sizeof(env)/sizeof(env[0]));
> 
> Should be "%zu\n", not "%d\n"

printf("%zu\n",sizeof(env)/sizeof(env[0]));
zu

issue with Tiny C compiler I guess (which claims to almost-fully support 
C99).


 > -- or you could use "%d\n" and cast the argument to int.

printf("%d\n",(int)(sizeof(env)/sizeof(env[0])));
1


> Incidentally, this declaration of main is not portable, but an
> optional third "env" parameter is a common extension.

Haven't tested it yet, but I assume it will run unchanged on Linux.



>> Apparently, in your execution environment,
>> a >>pointer to a pointer to char<< is the same size as a >>pointer to char<<
>> and, thus, division of the size of one by the size of the other gives a
>> value of 1
> 
> In principle, it could still yield 1 if, for example, sizeof (char**)
> == 6 and sizeof (char*) == 4.  But that detail in understanding
> the semantics of this semantically incorrect code is less important
> than fixing the code.

What here needs to be fixed?

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


#111848

Fromjameskuyper@verizon.net
Date2017-06-08 10:51 -0700
Message-ID<497ef66f-7fc4-43d8-a897-8d5599042e6e@googlegroups.com>
In reply to#111842
On Thursday, June 8, 2017 at 1:15:00 PM UTC-4, DFS wrote:
> On 6/8/2017 12:34 PM, Keith Thompson wrote:
> > Lew Pitcher <lew.pitcher@digitalfreehold.ca> writes:
> >> DFS wrote:
> >>> int main(int argc, char *argv[], char *env[])
> >>> {
> >>>     printf("%d\n",sizeof(env)/sizeof(env[0]));
> > 
> > Should be "%zu\n", not "%d\n"
> 
> printf("%zu\n",sizeof(env)/sizeof(env[0]));
> zu
> 
> issue with Tiny C compiler I guess (which claims to almost-fully support 
> C99).
> 
> 
>  > -- or you could use "%d\n" and cast the argument to int.
> 
> printf("%d\n",(int)(sizeof(env)/sizeof(env[0])));
> 1
> 
> 
> > Incidentally, this declaration of main is not portable, but an
> > optional third "env" parameter is a common extension.
> 
> Haven't tested it yet, but I assume it will run unchanged on Linux.
> 
> 
> 
> >> Apparently, in your execution environment,
> >> a >>pointer to a pointer to char<< is the same size as a >>pointer to char<<
> >> and, thus, division of the size of one by the size of the other gives a
> >> value of 1
> > 
> > In principle, it could still yield 1 if, for example, sizeof (char**)
> > == 6 and sizeof (char*) == 4.  But that detail in understanding
> > the semantics of this semantically incorrect code is less important
> > than fixing the code.
> 
> What here needs to be fixed?

The env parameter, while declared as an array, is actually a pointer. It points to the first element of an array of pointers. Your method of determining how many elements there are in that array doesn't work. The way you're supposed to figure it out is by going through that array, one element at a time, until you find a null pointer. That's what needs to be fixed.

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


#111826

FromGareth Owen <gwowen@gmail.com>
Date2017-06-08 16:56 +0100
Message-ID<878tl2v5ge.fsf@gmail.com>
In reply to#111820
DFS <nospam@dfs.com> writes:

> int main(int argc, char *argv[], char *env[])
> {
>   printf("%d\n",sizeof(env)/sizeof(env[0]));
>   return(0);
> )
>
> Output is 1.
>
> Why?

Anything that looks like an array object - when used in the argument
list of a function, is not an array object, but "decays" into a pointer.

so in

int foo(char *arr1[12])
{
   char *arr2[12];
   char **arr3;
}

arr1 and arr3 have the same type, even though
arr1 and arr2 have the same declaration.

A misfeature, but an explicable one.

There is no way to obtain the size of arr1 in foo() without passing it
in explicitly (or counting them using a sentinel such as NULL to mark
the end, as is done with environment variables)

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


#111831

FromDFS <nospam@dfs.com>
Date2017-06-08 12:18 -0400
Message-ID<ohbt7i$jm2$2@dont-email.me>
In reply to#111826
On 6/8/2017 11:56 AM, Gareth Owen wrote:
> DFS <nospam@dfs.com> writes:
> 
>> int main(int argc, char *argv[], char *env[])
>> {
>>    printf("%d\n",sizeof(env)/sizeof(env[0]));
>>    return(0);
>> )
>>
>> Output is 1.
>>
>> Why?
> 
> Anything that looks like an array object - when used in the argument
> list of a function, is not an array object, but "decays" into a pointer.
> 
> so in
> 
> int foo(char *arr1[12])
> {
>     char *arr2[12];
>     char **arr3;
> }
> 
> arr1 and arr3 have the same type, even though
> arr1 and arr2 have the same declaration.
> 
> A misfeature, but an explicable one.

Gotcha


> There is no way to obtain the size of arr1 in foo() without passing it
> in explicitly (or counting them using a sentinel such as NULL to mark
> the end, as is done with environment variables)

I want to check the Path env variable for the existence of a string:

\GNU\Win32\bin


I counted the env variables:

int envars=0;
while (*env!=NULL) {*env++;envars++;}
printf("%d\n",envars);
65

But then I can't go back and reference the values in env[] again because 
the pointer has moved to the end of the array (or past it?).

What would you suggest?

1) can I reset the pointer back to the beginning of env[]?   How?
2) make a copy of the env[] array and use it?  How do I make a copy?
3) can I create a new pointer pointing back to the beginning of env[]?  How?


Thanks

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


#111833

Fromscott@slp53.sl.home (Scott Lurndal)
Date2017-06-08 16:35 +0000
Message-ID<m1f_A.19254$5S7.2068@fx28.iad>
In reply to#111831
DFS <nospam@dfs.com> writes:
>On 6/8/2017 11:56 AM, Gareth Owen wrote:
>> DFS <nospam@dfs.com> writes:
>
>I want to check the Path env variable for the existence of a string:
>
>\GNU\Win32\bin
>
>
>I counted the env variables:
>
>int envars=0;
>while (*env!=NULL) {*env++;envars++;}
>printf("%d\n",envars);
>65
>
>But then I can't go back and reference the values in env[] again because 
>the pointer has moved to the end of the array (or past it?).
>
>What would you suggest?
>
>1) can I reset the pointer back to the beginning of env[]?   How?
>2) make a copy of the env[] array and use it?  How do I make a copy?
>3) can I create a new pointer pointing back to the beginning of env[]?  How?

#include <stdio.h>

int main(int argc, const char *argv[], const char *env[])
{
   const char **ep = env;
   unsigned count;

   for (count=0; *ep != NULL; ep++, count++) ;

   printf("%u\n",count);
   return(0);
}

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


#111837

FromLew Pitcher <lew.pitcher@digitalfreehold.ca>
Date2017-06-08 12:43 -0400
Message-ID<ohbuk2$p49$1@dont-email.me>
In reply to#111831
DFS wrote:

> On 6/8/2017 11:56 AM, Gareth Owen wrote:
>> DFS <nospam@dfs.com> writes:
>> 
>>> int main(int argc, char *argv[], char *env[])
>>> {
>>>    printf("%d\n",sizeof(env)/sizeof(env[0]));
>>>    return(0);
>>> )
>>>
>>> Output is 1.
>>>
>>> Why?
>> 
>> Anything that looks like an array object - when used in the argument
>> list of a function, is not an array object, but "decays" into a pointer.
>> 
>> so in
>> 
>> int foo(char *arr1[12])
>> {
>>     char *arr2[12];
>>     char **arr3;
>> }
>> 
>> arr1 and arr3 have the same type, even though
>> arr1 and arr2 have the same declaration.
>> 
>> A misfeature, but an explicable one.
> 
> Gotcha
> 
> 
>> There is no way to obtain the size of arr1 in foo() without passing it
>> in explicitly (or counting them using a sentinel such as NULL to mark
>> the end, as is done with environment variables)
> 
> I want to check the Path env variable for the existence of a string:
> 
> \GNU\Win32\bin
> 
> 
> I counted the env variables:
> 
> int envars=0;
> while (*env!=NULL) {*env++;envars++;}
> printf("%d\n",envars);
> 65
> 
> But then I can't go back and reference the values in env[] again because
> the pointer has moved to the end of the array (or past it?).
> 
> What would you suggest?
> 
> 1) can I reset the pointer back to the beginning of env[]?   How?

By taking another approach.

You can either make a copy of env (the pointer), and walk through the array 
using /that/, or

You can walk through the array using an index. Using your code (above) as an 
example, this might look like...

  int envars=0;
  while (env[envars]!=NULL) {envars++;}
  printf("%d\n",envars)

but, I'd probably write it something like...

  int envars;

  /* advance through env[] array, looking for NULL pointer */
  for (envars = 0; env[envars] != NULL; ++envars) {/*NOP*/}

  printf("%d\n",envars);

> 2) make a copy of the env[] array and use it?  How do I make a copy?

That's doable, but not the brightest move. You don't need a copy.
The code to do this would be more complex than you have now.

> 3) can I create a new pointer pointing back to the beginning of env[]? 

Using your code, above, you would do something like...

  char **beginning;
  int envars=0;

  beginning = env; /* beginning points the start of env[] array */

  while (*env!=NULL) {*env++;envars++;}
  printf("%d\n",envars);

> How?
> 
> 
> Thanks


-- 
Lew Pitcher
"In Skills, We Trust"
PGP public key available upon request

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


#111847

FromDFS <nospam@dfs.com>
Date2017-06-08 13:49 -0400
Message-ID<ohc2ha$7n2$1@dont-email.me>
In reply to#111837
On 6/8/2017 12:43 PM, Lew Pitcher wrote:


> but, I'd probably write it something like...
> 
>    int envars;
> 
>    /* advance through env[] array, looking for NULL pointer */
>    for (envars = 0; env[envars] != NULL; ++envars) {/*NOP*/}
> 
>    printf("%d\n",envars);


I just want to extract the Path env variable.

This code hangs.  Am I misusing strncpy?

int envars=0;
char tmp[5];
for (envars = 0; env[envars] != NULL; ++envars)
{
	strncpy(tmp,env[envars],5);
	tmp[5]='\0';
	if (strcmp(tmp,"Path=")==0)
	{
		printf("%d. %s\n", envars+1, env[envars]);
		break;
	}		
}
	

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


#111849

From"James R. Kuyper" <jameskuyper@verizon.net>
Date2017-06-08 13:58 -0400
Message-ID<42e3b033-99e2-d002-3b17-7314637f0095@verizon.net>
In reply to#111847
On 06/08/2017 01:49 PM, DFS wrote:
> On 6/8/2017 12:43 PM, Lew Pitcher wrote:
>
>
>> but, I'd probably write it something like...
>>
>>    int envars;
>>
>>    /* advance through env[] array, looking for NULL pointer */
>>    for (envars = 0; env[envars] != NULL; ++envars) {/*NOP*/}
>>
>>    printf("%d\n",envars);
>
>
> I just want to extract the Path env variable.
>
> This code hangs.  Am I misusing strncpy?

No, you're misusing tmp.

> int envars=0;
> char tmp[5];
> for (envars = 0; env[envars] != NULL; ++envars)
> {
> 	strncpy(tmp,env[envars],5);
> 	tmp[5]='\0';

You only declared tmp as having 5 elements: tmp[0], tmp[1], tmp[2], 
tmp[3], and tmp[4]. There is no such object as tmp[5]. Increase the size 
to 6, and your code should work (note: I'm far more reliable when I say 
"I see a defect" than when I say "I see no defects").

> 	if (strcmp(tmp,"Path=")==0)
> 	{
> 		printf("%d. %s\n", envars+1, env[envars]);
> 		break;
> 	}		
> }

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


#111855

FromDFS <nospam@dfs.com>
Date2017-06-08 14:45 -0400
Message-ID<ohc5q2$jn7$2@dont-email.me>
In reply to#111849
On 6/8/2017 1:58 PM, James R. Kuyper wrote:
> On 06/08/2017 01:49 PM, DFS wrote:

>> This code hangs.  Am I misusing strncpy?
> 
> No, you're misusing tmp.
> 
>> int envars=0;
>> char tmp[5];
>> for (envars = 0; env[envars] != NULL; ++envars)
>> {
>>     strncpy(tmp,env[envars],5);
>>     tmp[5]='\0';
> 
> You only declared tmp as having 5 elements: tmp[0], tmp[1], tmp[2], 
> tmp[3], and tmp[4]. There is no such object as tmp[5]. Increase the size 
> to 6, and your code should work 

And indeed it does!  Suhweet!


> (note: I'm far more reliable when I say 
> "I see a defect" than when I say "I see no defects").

Thanks for those eagle eyes!

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


#111857

FromKeith Thompson <kst-u@mib.org>
Date2017-06-08 12:10 -0700
Message-ID<lnmv9ii9dd.fsf@kst-u.example.com>
In reply to#111847
DFS <nospam@dfs.com> writes:
> On 6/8/2017 12:43 PM, Lew Pitcher wrote:
>> but, I'd probably write it something like...
>> 
>>    int envars;
>> 
>>    /* advance through env[] array, looking for NULL pointer */
>>    for (envars = 0; env[envars] != NULL; ++envars) {/*NOP*/}
>> 
>>    printf("%d\n",envars);
>
>
> I just want to extract the Path env variable.



> This code hangs.  Am I misusing strncpy?
>
> int envars=0;
> char tmp[5];
> for (envars = 0; env[envars] != NULL; ++envars)
> {
> 	strncpy(tmp,env[envars],5);
> 	tmp[5]='\0';

Apart from the fact that you're assigning a value to the nonexisting
tmp[5] (which has already been covered), creating a copy of the initial
portion of the string is unnecessary.  Just use strncmp().

And be careful with strncpy(); it's not just a "safer" version of
strcpy().  (Usually the best way to be careful with it is to avoid using
it.)

> 	if (strcmp(tmp,"Path=")==0)
> 	{
> 		printf("%d. %s\n", envars+1, env[envars]);
> 		break;
> 	}		
> }

On Unix-like systems, there's an environment variable named "PATH", not
"Path".

I'm not sure about Windows.  As I recall it does use a similarly named
environment variable, but a lot of things in Windows are
case-insensitive.  I don't know whether you can rely on it being called
"Path" rather than, say, "path" or PATH".

And if your goal is to get the value of a particular environment
variable, I recommend the standard getenv() function.

-- 
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]


#111881

FromDFS <nospam@dfs.com>
Date2017-06-09 11:21 -0400
Message-ID<ohee7e$f5c$1@dont-email.me>
In reply to#111857
On 6/8/2017 3:10 PM, Keith Thompson wrote:


> On Unix-like systems, there's an environment variable named "PATH", not
> "Path".
> 
> I'm not sure about Windows.  As I recall it does use a similarly named
> environment variable, but a lot of things in Windows are
> case-insensitive.  I don't know whether you can rely on it being called
> "Path" rather than, say, "path" or PATH".
> 
> And if your goal is to get the value of a particular environment
> variable, I recommend the standard getenv() function.


Any case of 'path' works on Windows:

getenv("Path")
getenv("path")
getenv("PATH")
getenv("pAtH")


You and jak (in another thread) mentioned getenv().  It's perfect:

test if(strstr(getenv("Path"),"string") against NULL


Thanks for your help.

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


#111882

FromRichard Heathfield <rjh@cpax.org.uk>
Date2017-06-09 16:23 +0100
Message-ID<oheeb7$eu4$1@dont-email.me>
In reply to#111857
On 08/06/17 20:10, Keith Thompson wrote:
> And be careful with strncpy(); it's not just a "safer" version of
> strcpy().

In fact, it's not /even/ a "safer" version of strcpy().

> (Usually the best way to be careful with it is to avoid using
> it.)

Legitimate uses of strncpy are indeed rare. As you hint, however, we 
lack a proof that they do not exist.

-- 
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]


#111885

From"James R. Kuyper" <jameskuyper@verizon.net>
Date2017-06-09 11:48 -0400
Message-ID<b3cd0b00-fc9b-cd50-6476-b31e66c44882@verizon.net>
In reply to#111882
On 06/09/2017 11:23 AM, Richard Heathfield wrote:
> On 08/06/17 20:10, Keith Thompson wrote:
>> And be careful with strncpy(); it's not just a "safer" version of
>> strcpy().
>
> In fact, it's not /even/ a "safer" version of strcpy().
>
>> (Usually the best way to be careful with it is to avoid using
>> it.)
>
> Legitimate uses of strncpy are indeed rare. As you hint, however, we
> lack a proof that they do not exist.

I've cited a case that comes up frequently in my own code which Keith 
conceded was an appropriate use. Had you forgotten it, or do you disagree?

I have an output file format that I'm not free to modify, which contains 
fixed-length text fields. The text that should be placed in many of 
those fields is not guaranteed to be small enough to fit, in which case 
I'm permitted to truncate it. Since fixed width of the fields is 
documented, they don't need null termination, and we want to lose as 
little text as possible to truncation. Therefore, if the field is, for 
instance, 40 characters long, and the input is 50 characters long, I put 
the 40th character from the input source into field[39], rather than 
'\0'. When reading such fields, I never assume that they're null 
terminated: I read them into, for instance, the first 40 bytes of a 
41-byte array, and then execute field[40]='\0' before passing them to 
any routine that expects null-termination.

I frequently need to confirm that two different runs of my program 
displayed only the expected differences (if any) in the output file. The 
tools I have available for examining the contents of these files look at 
the entire length of the fixed-length text fields, not just the part 
before the terminating null character (if there is one). As a result, if 
I don't pay attention to what's put into the field after the terminating 
null character, it's likely to contain garbage, and most importantly, 
it's likely to contain different garbage during different runs of the 
program, producing spurious indications that the files differ. 
Therefore, if the input is 30 characters long, and the output is 40 
characters, I want the last 10 bytes to all consistently contain '\0', 
to make it easier to compare the files.

Do you think this is an appropriate context for using strncpy()? It 
certainly seems that way to me. The first time I described it, Keith 
said that it seemed almost tailor-made for strncpy().

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


#111887

FromRichard Heathfield <rjh@cpax.org.uk>
Date2017-06-09 16:53 +0100
Message-ID<oheg3n$m2f$1@dont-email.me>
In reply to#111885
On 09/06/17 16:48, James R. Kuyper wrote:
> On 06/09/2017 11:23 AM, Richard Heathfield wrote:
>> On 08/06/17 20:10, Keith Thompson wrote:
>>> And be careful with strncpy(); it's not just a "safer" version of
>>> strcpy().
>>
>> In fact, it's not /even/ a "safer" version of strcpy().
>>
>>> (Usually the best way to be careful with it is to avoid using
>>> it.)
>>
>> Legitimate uses of strncpy are indeed rare. As you hint, however, we
>> lack a proof that they do not exist.
>
> I've cited a case that comes up frequently in my own code which Keith
> conceded was an appropriate use. Had you forgotten it,

I didn't see it. I've recently done a catch-up "Mark All As Read".

Okay, so we have the opposite - an existence proof. Fine by me. :-)

> or do you disagree?

No, of course not. But I would still maintain that the number of 
legitimate applications of strncpy is perhaps somewhat limited in 
comparison to strcpy or even memcpy.

> I have an output file format that I'm not free to modify, which contains
> fixed-length text fields. The text that should be placed in many of
> those fields is not guaranteed to be small enough to fit, in which case
> I'm permitted to truncate it. Since fixed width of the fields is
> documented, they don't need null termination, and we want to lose as
> little text as possible to truncation. Therefore, if the field is, for
> instance, 40 characters long, and the input is 50 characters long, I put
> the 40th character from the input source into field[39], rather than
> '\0'. When reading such fields, I never assume that they're null
> terminated: I read them into, for instance, the first 40 bytes of a
> 41-byte array, and then execute field[40]='\0' before passing them to
> any routine that expects null-termination.
>
> I frequently need to confirm that two different runs of my program
> displayed only the expected differences (if any) in the output file. The
> tools I have available for examining the contents of these files look at
> the entire length of the fixed-length text fields, not just the part
> before the terminating null character (if there is one). As a result, if
> I don't pay attention to what's put into the field after the terminating
> null character, it's likely to contain garbage, and most importantly,
> it's likely to contain different garbage during different runs of the
> program, producing spurious indications that the files differ.
> Therefore, if the input is 30 characters long, and the output is 40
> characters, I want the last 10 bytes to all consistently contain '\0',
> to make it easier to compare the files.

Hmmm. If you want my advice, use strncpy. I'm surprised you didn't think 
of it yourself. It's almost tailor-made for this kind of thing.

-- 
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]


#111889

From"James R. Kuyper" <jameskuyper@verizon.net>
Date2017-06-09 12:18 -0400
Message-ID<074e99ae-c55d-ae8a-c116-458fea076c79@verizon.net>
In reply to#111887
On 06/09/2017 11:53 AM, Richard Heathfield wrote:
> On 09/06/17 16:48, James R. Kuyper wrote:
>> On 06/09/2017 11:23 AM, Richard Heathfield wrote:
>>> On 08/06/17 20:10, Keith Thompson wrote:
>>>> And be careful with strncpy(); it's not just a "safer" version of
>>>> strcpy().
>>>
>>> In fact, it's not /even/ a "safer" version of strcpy().
>>>
>>>> (Usually the best way to be careful with it is to avoid using
>>>> it.)
>>>
>>> Legitimate uses of strncpy are indeed rare. As you hint, however, we
>>> lack a proof that they do not exist.
>>
>> I've cited a case that comes up frequently in my own code which Keith
>> conceded was an appropriate use. Had you forgotten it,
>
> I didn't see it. I've recently done a catch-up "Mark All As Read".

I've explained it several times during the past couple of decades, but 
not recently. I was challenging your long-term memory, not your short 
term. I am, incidentally, in no position to criticize anyone else's 
memory, and that wasn't meant as criticism.

> Okay, so we have the opposite - an existence proof. Fine by me. :-)
>
>> or do you disagree?
>
> No, of course not. But I would still maintain that the number of
> legitimate applications of strncpy is perhaps somewhat limited in
> comparison to strcpy or even memcpy.

Oh, that's certainly the case.

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


#111890

FromRichard Heathfield <rjh@cpax.org.uk>
Date2017-06-09 17:28 +0100
Message-ID<ohei4c$st4$1@dont-email.me>
In reply to#111889
On 09/06/17 17:18, James R. Kuyper wrote:
> On 06/09/2017 11:53 AM, Richard Heathfield wrote:
>> On 09/06/17 16:48, James R. Kuyper wrote:
>>> On 06/09/2017 11:23 AM, Richard Heathfield wrote:
>>>> On 08/06/17 20:10, Keith Thompson wrote:
>>>>> And be careful with strncpy(); it's not just a "safer" version of
>>>>> strcpy().
>>>>
>>>> In fact, it's not /even/ a "safer" version of strcpy().
>>>>
>>>>> (Usually the best way to be careful with it is to avoid using
>>>>> it.)
>>>>
>>>> Legitimate uses of strncpy are indeed rare. As you hint, however, we
>>>> lack a proof that they do not exist.
>>>
>>> I've cited a case that comes up frequently in my own code which Keith
>>> conceded was an appropriate use. Had you forgotten it,
>>
>> I didn't see it. I've recently done a catch-up "Mark All As Read".
>
> I've explained it several times during the past couple of decades, but
> not recently. I was challenging your long-term memory, not your short
> term.

My long-term memory is a curate's egg - good in parts.

> I am, incidentally, in no position to criticize anyone else's
> memory, and that wasn't meant as criticism.

I didn't take it as criticism, uh, uh, Keith. No, not Keith. Um...

-- 
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]


#111888

FromKeith Thompson <kst-u@mib.org>
Date2017-06-09 09:12 -0700
Message-ID<lna85hi1i4.fsf@kst-u.example.com>
In reply to#111885
"James R. Kuyper" <jameskuyper@verizon.net> writes:
> On 06/09/2017 11:23 AM, Richard Heathfield wrote:
>> On 08/06/17 20:10, Keith Thompson wrote:
>>> And be careful with strncpy(); it's not just a "safer" version of
>>> strcpy().
>> In fact, it's not /even/ a "safer" version of strcpy().

Agreed.

>>> (Usually the best way to be careful with it is to avoid using
>>> it.)
>>
>> Legitimate uses of strncpy are indeed rare. As you hint, however, we
>> lack a proof that they do not exist.
>
> I've cited a case that comes up frequently in my own code which Keith 
> conceded was an appropriate use. Had you forgotten it, or do you disagree?

I believe Richard was acknowledging the possible existence of cases
where using strncpy is legitimate.

> I have an output file format that I'm not free to modify, which contains 
> fixed-length text fields. The text that should be placed in many of 
> those fields is not guaranteed to be small enough to fit, in which case 
> I'm permitted to truncate it. Since fixed width of the fields is 
> documented, they don't need null termination, and we want to lose as 
> little text as possible to truncation.
[snip]

Yes, that's just the (somewhat rare) kind of data format that strncpy is
designed to work with.

I might as well post this link again:

http://the-flat-trantor-society.blogspot.com/2012/03/no-strncpy-is-not-safer-strcpy.html

-- 
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]


Page 1 of 3  [1] 2 3  Next page →

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


csiph-web