Rocksolid Light

Welcome to novaBBS (click a section below)

mail  files  register  newsreader  groups  login

Message-ID:  

The unrecognized minister of propaganda, E -- seen in an email from Ean Schuessler


devel / comp.lang.c / Re: on looking up a word in a table, pointer question

SubjectAuthor
* on looking up a word in a table, pointer questionMeredith Montgomery
+- Re: on looking up a word in a table, pointer questionStefan Ram
+- Re: on looking up a word in a table, pointer questionScott Lurndal
+- Re: on looking up a word in a table, pointer questionMeredith Montgomery
+* Re: on looking up a word in a table, pointer questionKaz Kylheku
|`- Re: on looking up a word in a table, pointer questionMeredith Montgomery
+* Re: on looking up a word in a table, pointer questionBen Bacarisse
|+- Re: on looking up a word in a table, pointer questionMeredith Montgomery
|`- Re: on looking up a word in a table, pointer questionJames Kuyper
`* Re: on looking up a word in a table, pointer questionLew Pitcher
 +* Re: on looking up a word in a table, pointer questionLew Pitcher
 |`* Re: on looking up a word in a table, pointer questionBen Bacarisse
 | `* Re: on looking up a word in a table, pointer questionMeredith Montgomery
 |  `- Re: on looking up a word in a table, pointer questionBart
 `- Re: on looking up a word in a table, pointer questionMike Terry

1
on looking up a word in a table, pointer question

<86k0ejbly8.fsf@levado.to>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=20244&group=comp.lang.c#20244

  copy link   Newsgroups: comp.lang.c
Path: i2pn2.org!i2pn.org!aioe.org!SZor4ZqbvgPVVsWQ21e4cw.user.46.165.242.75.POSTED!not-for-mail
From: mmontgom...@levado.to (Meredith Montgomery)
Newsgroups: comp.lang.c
Subject: on looking up a word in a table, pointer question
Date: Fri, 28 Jan 2022 18:16:15 -0300
Organization: Aioe.org NNTP Server
Message-ID: <86k0ejbly8.fsf@levado.to>
Mime-Version: 1.0
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: 8bit
Injection-Info: gioia.aioe.org; logging-data="21660"; posting-host="SZor4ZqbvgPVVsWQ21e4cw.user.gioia.aioe.org"; mail-complaints-to="abuse@aioe.org";
X-Notice: Filtered by postfilter v. 0.9.2
Cancel-Lock: sha1:YazqhrN3bVSLlJHaQIRV+35Y0CI=
 by: Meredith Montgomery - Fri, 28 Jan 2022 21:16 UTC

I show the full program at the end of this message, but I bet you don't
need the full program.

Here's a table of C keywords:

--8<---------------cut here---------------start------------->8---
struct kw {
char *word;
int count;
};

struct kw table[] = {
{"break", 0},
{"case", 0},
{"char", 0},
{"const", 0},
{"int", 0},
{"continue", 0},
{"default", 0},
{"unsigned", 0},
{"void", 0},
{"volatile", 0},
{"while", 0}
};
--8<---------------cut here---------------end--------------->8---

Here's a procedure to lookup a word in this table:

--8<---------------cut here---------------start------------->8---
struct kw * lookup(char *word, struct kw * table, int n) {
struct kw *p;

for ( p = table; p->word != NULL; p++) {
if (strcmp(word, p->word) == 0)
return p;
}

return NULL; /* not found */
} --8<---------------cut here---------------end--------------->8---

Notice how I'm stopping when p->word is not NULL. This happens when p
gets to the last element of that array, which is terminated with a zero
automatically by the compiler. (Just like a c-string.) (I suppose.)

So far so good.

But this is not what I wrote first. I'm stepping p through each element
in the table, so I know that eventually p points to the last element of
the array which is a certain zero-thing. So the more natural comparison
to me would be something like

*p != NULL

but the compiler won't let me because it says that *p has type

struct kw,

which cannot be compared with

void *.

%make keywords2
cc -x c -g -std=c99 -pedantic-errors -c -o keywords2.o keywords2.c
keywords2.c: In function ‘lookup’:
keywords2.c:48:23: error: invalid operands to binary != (have ‘struct kw’ and ‘void *’)
48 | for ( p = table; *p != NULL; p++) {
| ~~ ^~
| |
| struct kw
make: *** [<builtin>: keywords2.o] Error 1
%

This makes perfect sense. But how could I detect that p has reached the
end of the table in a more natural way than p->word? What is the
standard way to write this? Thank you.

(*) Full program

#include <ctype.h>
#include <string.h>
#include <stdio.h>

#define NKEYS ((sizeof table) / (sizeof table[0]))
#define MAXWORD 100

int getword(char *, int);
struct kw * lookup(char *, struct kw *, int);

struct kw {
char *word;
int count;
};

struct kw table[] = {
{"break", 0},
{"case", 0},
{"char", 0},
{"const", 0},
{"int", 0},
{"continue", 0},
{"default", 0},
{"unsigned", 0},
{"void", 0},
{"volatile", 0},
{"while", 0}
};

int main() {
int n; char word[MAXWORD]; struct kw * p;

while (getword(word, MAXWORD) != EOF)
if (isalpha(word[0]))
if ((p = lookup(word, table, NKEYS)) != NULL)
p->count++;

for (p = table; p < table + NKEYS; p++)
if (p->count > 0)
printf("%4d %s\n", p->count, p->word);

return 0;
}

struct kw * lookup(char *word, struct kw * table, int n) {
struct kw *p;

for ( p = table; *p != NULL; p++) {
if (strcmp(word, p->word) == 0)
return p;
}

return NULL; /* not found */
}

int getword(char *word, int lim) {
int getch(void);
void ungetch(int);

int c;
char *w = word;

while (isspace(c = getch()))
;

if (c != EOF)
*w++ = c;

if (!isalpha(c)) {
*w = '\0';
return c;
}

for ( ; --lim > 0; w++)
if (!isalnum(*w = getch())) {
ungetch(*w);
break;
}

*w = '\0';
return word[0];
}

Re: on looking up a word in a table, pointer question

<arrays-20220128222644@ram.dialup.fu-berlin.de>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=20247&group=comp.lang.c#20247

  copy link   Newsgroups: comp.lang.c
Path: i2pn2.org!i2pn.org!aioe.org!news.freedyn.de!speedkom.net!fu-berlin.de!uni-berlin.de!not-for-mail
From: ram...@zedat.fu-berlin.de (Stefan Ram)
Newsgroups: comp.lang.c
Subject: Re: on looking up a word in a table, pointer question
Date: 28 Jan 2022 21:29:06 GMT
Organization: Stefan Ram
Lines: 12
Expires: 1 Apr 2022 11:59:58 GMT
Message-ID: <arrays-20220128222644@ram.dialup.fu-berlin.de>
References: <86k0ejbly8.fsf@levado.to>
Mime-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
X-Trace: news.uni-berlin.de G+byf2M+mIiqeQwrEaYjhgK2C+tpvjjc13bkefGU0m7d6h
X-Copyright: (C) Copyright 2022 Stefan Ram. All rights reserved.
Distribution through any means other than regular usenet
channels is forbidden. It is forbidden to publish this
article in the Web, to change URIs of this article into links,
and to transfer the body without this notice, but quotations
of parts in other Usenet posts are allowed.
X-No-Archive: Yes
Archive: no
X-No-Archive-Readme: "X-No-Archive" is set, because this prevents some
services to mirror the article in the web. But the article may
be kept on a Usenet archive server with only NNTP access.
X-No-Html: yes
Content-Language: en-US
Accept-Language: de-DE, en-US, it, fr-FR
 by: Stefan Ram - Fri, 28 Jan 2022 21:29 UTC

Meredith Montgomery <mmontgomery@levado.to> writes:
> the last element of that array, which is terminated with a zero
>automatically by the compiler. (Just like a c-string.) (I suppose.)

An array is not zero-terminated in this way.

>This makes perfect sense. But how could I detect that p has reached the
>end of the table in a more natural way than p->word?

p->word is fine. If it ain't broke, don't fix it.

Re: on looking up a word in a table, pointer question

<YeZIJ.21452$V31.12889@fx47.iad>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=20248&group=comp.lang.c#20248

  copy link   Newsgroups: comp.lang.c
Path: i2pn2.org!i2pn.org!weretis.net!feeder8.news.weretis.net!news.roellig-ltd.de!open-news-network.org!peer03.ams4!peer.am4.highwinds-media.com!peer02.iad!feed-me.highwinds-media.com!news.highwinds-media.com!fx47.iad.POSTED!not-for-mail
X-newsreader: xrn 9.03-beta-14-64bit
Sender: scott@dragon.sl.home (Scott Lurndal)
From: sco...@slp53.sl.home (Scott Lurndal)
Reply-To: slp53@pacbell.net
Subject: Re: on looking up a word in a table, pointer question
Newsgroups: comp.lang.c
References: <86k0ejbly8.fsf@levado.to>
Lines: 194
Message-ID: <YeZIJ.21452$V31.12889@fx47.iad>
X-Complaints-To: abuse@usenetserver.com
NNTP-Posting-Date: Fri, 28 Jan 2022 21:29:28 UTC
Organization: UsenetServer - www.usenetserver.com
Date: Fri, 28 Jan 2022 21:29:28 GMT
X-Received-Bytes: 5405
 by: Scott Lurndal - Fri, 28 Jan 2022 21:29 UTC

Meredith Montgomery <mmontgomery@levado.to> writes:
>I show the full program at the end of this message, but I bet you don't
>need the full program.
>
>Here's a table of C keywords:
>
>--8<---------------cut here---------------start------------->8---
>struct kw {
> char *word;
> int count;
>};
>
>struct kw table[] = {
> {"break", 0},
> {"case", 0},
> {"char", 0},
> {"const", 0},
> {"int", 0},
> {"continue", 0},
> {"default", 0},
> {"unsigned", 0},
> {"void", 0},
> {"volatile", 0},
> {"while", 0}
>};
>--8<---------------cut here---------------end--------------->8---
>
>Here's a procedure to lookup a word in this table:
>
>--8<---------------cut here---------------start------------->8---
>struct kw * lookup(char *word, struct kw * table, int n) {
> struct kw *p;
>
> for ( p = table; p->word != NULL; p++) {
> if (strcmp(word, p->word) == 0)
> return p;
> }
>
> return NULL; /* not found */
>}
>--8<---------------cut here---------------end--------------->8---
>
>Notice how I'm stopping when p->word is not NULL. This happens when p
>gets to the last element of that array, which is terminated with a zero
>automatically by the compiler. (Just like a c-string.) (I suppose.)
>
>So far so good.
>
>But this is not what I wrote first. I'm stepping p through each element
>in the table, so I know that eventually p points to the last element of
>the array which is a certain zero-thing. So the more natural comparison
>to me would be something like
>
> *p != NULL
>
>but the compiler won't let me because it says that *p has type
>
> struct kw,
>
>which cannot be compared with
>
> void *.
>
>%make keywords2
>cc -x c -g -std=c99 -pedantic-errors -c -o keywords2.o keywords2.c
>keywords2.c: In function ‘lookup’:
>keywords2.c:48:23: error: invalid operands to binary != (have ‘struct kw’ and ‘void *’)
> 48 | for ( p = table; *p != NULL; p++) {
> | ~~ ^~
> | |
> | struct kw
>make: *** [<builtin>: keywords2.o] Error 1
>%
>
>This makes perfect sense. But how could I detect that p has reached the
>end of the table in a more natural way than p->word? What is the
>standard way to write this? Thank you.
>
>(*) Full program
>
>#include <ctype.h>
>#include <string.h>
>#include <stdio.h>
>
>#define NKEYS ((sizeof table) / (sizeof table[0]))
>#define MAXWORD 100
>
>int getword(char *, int);
>struct kw * lookup(char *, struct kw *, int);
>
>struct kw {
> char *word;
> int count;
>};
>
>struct kw table[] = {
> {"break", 0},
> {"case", 0},
> {"char", 0},
> {"const", 0},
> {"int", 0},
> {"continue", 0},
> {"default", 0},
> {"unsigned", 0},
> {"void", 0},
> {"volatile", 0},
> {"while", 0}
>};
>
>int main() {
> int n; char word[MAXWORD]; struct kw * p;
>
> while (getword(word, MAXWORD) != EOF)
> if (isalpha(word[0]))
> if ((p = lookup(word, table, NKEYS)) != NULL)
> p->count++;
>
> for (p = table; p < table + NKEYS; p++)
> if (p->count > 0)
> printf("%4d %s\n", p->count, p->word);
>
> return 0;
>}
>
>struct kw * lookup(char *word, struct kw * table, int n) {
> struct kw *p;
>
> for ( p = table; *p != NULL; p++) {
> if (strcmp(word, p->word) == 0)
> return p;
> }
>
> return NULL; /* not found */
>}
>
>int getword(char *word, int lim) {
> int getch(void);
> void ungetch(int);
>
> int c;
> char *w = word;
>
> while (isspace(c = getch()))
> ;
>
> if (c != EOF)
> *w++ = c;
>
> if (!isalpha(c)) {
> *w = '\0';
> return c;
> }
>
> for ( ; --lim > 0; w++)
> if (!isalnum(*w = getch())) {
> ungetch(*w);
> break;
> }
>
> *w = '\0';
> return word[0];
>}

for(tp=commands, i=0; i < MAX_COMMAND_INTERP_COMMANDS; i++,tp++) {
if (tp->name[0] != '\0') {
/*
* If this command is allowed to be abbreviated,
* check to see if this is it.
*/

if (tp->minlen
&& (strlen(argv[0]) <= tp->minlen)) {
if (strncmp(argv[0],
tp->name,
tp->minlen) == 0) {
break;
}
}

if (strcmp(argv[0], tp->name)==0) {
break;
}
}
}

if (i < MAX_COMMAND_INTERP_COMMANDS) {
if (tp->thisarg) {
return (*tp->thisfunc)(tp->thisarg, argc, (const char **)argv, env);
} else {
return (*tp->func)(argc, (const char **)argv, env);
}
}

Re: on looking up a word in a table, pointer question

<865yq3bkf6.fsf@levado.to>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=20251&group=comp.lang.c#20251

  copy link   Newsgroups: comp.lang.c
Path: i2pn2.org!i2pn.org!aioe.org!SZor4ZqbvgPVVsWQ21e4cw.user.46.165.242.75.POSTED!not-for-mail
From: mmontgom...@levado.to (Meredith Montgomery)
Newsgroups: comp.lang.c
Subject: Re: on looking up a word in a table, pointer question
Date: Fri, 28 Jan 2022 18:49:17 -0300
Organization: Aioe.org NNTP Server
Message-ID: <865yq3bkf6.fsf@levado.to>
References: <86k0ejbly8.fsf@levado.to>
Mime-Version: 1.0
Content-Type: text/plain
Injection-Info: gioia.aioe.org; logging-data="49223"; posting-host="SZor4ZqbvgPVVsWQ21e4cw.user.gioia.aioe.org"; mail-complaints-to="abuse@aioe.org";
X-Notice: Filtered by postfilter v. 0.9.2
Cancel-Lock: sha1:OnkF0oL60snZpAsgW0RwaHK+ZXk=
 by: Meredith Montgomery - Fri, 28 Jan 2022 21:49 UTC

Sorry. This post turned out to be a case of being tired.

> struct kw * lookup(char *word, struct kw * table, int n) {
> struct kw *p;
>
> for ( p = table; p->word != NULL; p++) {
> if (strcmp(word, p->word) == 0)
> return p;
> }
>
> return NULL; /* not found */
> }

The reason the argument n is there is precisely to be the size of the
table so that we can write the for loop's test as

p < table + n

Here's a revise version of lookup():

--8<---------------cut here---------------start------------->8---
struct kw * lookup(char *word, struct kw * table, int n) {
struct kw *p;
for (p = table; p < table + n; p++) {
if (strcmp(word, p->word) == 0)
return p;
}

return NULL; /* not found */
} --8<---------------cut here---------------end--------------->8---

This loop is pretty natural to me. I was being bitten, too, by the fact
that in main() I had an array and in lookup() I had just a pointer to an
element of the table. The NKEYS macro, therefore, doesn't work as I
expected inside lookup(). I was bitten there.

Re: on looking up a word in a table, pointer question

<20220128135506.266@kylheku.com>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=20254&group=comp.lang.c#20254

  copy link   Newsgroups: comp.lang.c
Path: i2pn2.org!i2pn.org!eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail
From: 480-992-...@kylheku.com (Kaz Kylheku)
Newsgroups: comp.lang.c
Subject: Re: on looking up a word in a table, pointer question
Date: Fri, 28 Jan 2022 22:07:05 -0000 (UTC)
Organization: A noiseless patient Spider
Lines: 130
Message-ID: <20220128135506.266@kylheku.com>
References: <86k0ejbly8.fsf@levado.to>
Injection-Date: Fri, 28 Jan 2022 22:07:05 -0000 (UTC)
Injection-Info: reader02.eternal-september.org; posting-host="b518d32d060c77aff006bc0c461b1e07";
logging-data="24165"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1/yYXG/PqHcKBtryopFxMoE7x438U/LnUs="
User-Agent: slrn/1.0.3 (Linux)
Cancel-Lock: sha1:YWuwSrgTspENhtM64+VY8It+Tvk=
 by: Kaz Kylheku - Fri, 28 Jan 2022 22:07 UTC

On 2022-01-28, Meredith Montgomery <mmontgomery@levado.to> wrote:
> I show the full program at the end of this message, but I bet you don't
> need the full program.
>
> Here's a table of C keywords:
>
> --8<---------------cut here---------------start------------->8---
> struct kw {
> char *word;
> int count;
> };
>
> struct kw table[] = {
> {"break", 0},
> {"case", 0},
> {"char", 0},
> {"const", 0},
> {"int", 0},
> {"continue", 0},
> {"default", 0},
> {"unsigned", 0},
> {"void", 0},
> {"volatile", 0},
> {"while", 0}
> };
> --8<---------------cut here---------------end--------------->8---
>
> Here's a procedure to lookup a word in this table:
>
> --8<---------------cut here---------------start------------->8---
> struct kw * lookup(char *word, struct kw * table, int n) {
> struct kw *p;
>
> for ( p = table; p->word != NULL; p++) {
> if (strcmp(word, p->word) == 0)
> return p;
> }
>
> return NULL; /* not found */
> }
> --8<---------------cut here---------------end--------------->8---
>
> Notice how I'm stopping when p->word is not NULL.

So you need an entry for that in the array

{"while", 0},
{NULL, 0}
};

> };
> This happens when p gets to the last element.

"gets" is deprecated in C, please say "moves" or "mosies on over to" or
some other more precise word. :)

> to the last element of that array, which is terminated with a zero
> automatically by the compiler. (Just like a c-string.) (I suppose.)
>
> So far so good.
>
> But this is not what I wrote first. I'm stepping p through each element
> in the table, so I know that eventually p points to the last element of
> the array which is a certain zero-thing.

The last element of the array is the {"while", 0} entry.

So the more natural comparison
> to me would be something like
>
> *p != NULL
>
> but the compiler won't let me because it says that *p has type
>
> struct kw,
>
> which cannot be compared with
>
> void *.

That could be arrangd, but provides no benefit:

int null_kw(struct kw kw)
{
return kw.word == NULL && kw.count == 0;
}

So then, provided you have the {NULL, 0} entry in the table. the loop
could terminate like this:

for (p = table; !null_kw(*p); p++)

That's a lot of ceremony for something simple. Or even

struct kw NULL_kw = { NULL, 0 };

for (p = table; !kw_compare(*p, NULL_kw); p++)

where we have this:

int kw_compare(struct kw left, struct kw right)
{
return ((left.word == NULL && right.word == NULL) ||
(left.word != NULL && right.word != NULL &&
strcmp(left.word, right.word) == 0)) &&
left.count == right.count;
}

All these kinds of idioms have their right time and place; probably
not here though in the simple loop through a table of keywords.

> This makes perfect sense. But how could I detect that p has reached the
> end of the table in a more natural way than p->word? What is the
> standard way to write this? Thank you.

Comparing p->word to NULL and ensuring there such an entry at the end
of the array is natural.

Another way is this:

/* caution: this macro invites an array_size(pointer) bug */

#define num_elements(array) (sizeof array / sizeof array[0])

/* ... */

for (i = 0; i < num_elements(table); i++) {
if (strcmp(table[i], word) == 0)
return &table[i];
}

Re: on looking up a word in a table, pointer question

<87h79nzehy.fsf@bsb.me.uk>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=20256&group=comp.lang.c#20256

  copy link   Newsgroups: comp.lang.c
Path: i2pn2.org!i2pn.org!eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail
From: ben.use...@bsb.me.uk (Ben Bacarisse)
Newsgroups: comp.lang.c
Subject: Re: on looking up a word in a table, pointer question
Date: Fri, 28 Jan 2022 22:23:21 +0000
Organization: A noiseless patient Spider
Lines: 98
Message-ID: <87h79nzehy.fsf@bsb.me.uk>
References: <86k0ejbly8.fsf@levado.to>
Mime-Version: 1.0
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: 8bit
Injection-Info: reader02.eternal-september.org; posting-host="2fd198c08059286dc1c2569557b90fa9";
logging-data="8216"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX19l0TE+bNScteNNh9cszUQTO/s9KVGuslM="
Cancel-Lock: sha1:C3ypU88KNGMZ1yLICAFOSJa7MhA=
sha1:X68Kt/wrXfYbjfbmRAlywVMxtt0=
X-BSB-Auth: 1.48d5500fcd947c939626.20220128222321GMT.87h79nzehy.fsf@bsb.me.uk
 by: Ben Bacarisse - Fri, 28 Jan 2022 22:23 UTC

Meredith Montgomery <mmontgomery@levado.to> writes:

> I show the full program at the end of this message, but I bet you don't
> need the full program.
>
> Here's a table of C keywords:
>
> struct kw {
> char *word;
> int count;
> };
>
> struct kw table[] = {
> {"break", 0},
> {"case", 0},
> {"char", 0},
> {"const", 0},
> {"int", 0},
> {"continue", 0},
> {"default", 0},
> {"unsigned", 0},
> {"void", 0},
> {"volatile", 0},
> {"while", 0}
> };
>
>
> Here's a procedure to lookup a word in this table:
>
> struct kw * lookup(char *word, struct kw * table, int n) {
> struct kw *p;
>
> for ( p = table; p->word != NULL; p++) {
> if (strcmp(word, p->word) == 0)
> return p;
> }
>
> return NULL; /* not found */
> }
>
> Notice how I'm stopping when p->word is not NULL. This happens when p
> gets to the last element of that array, which is terminated with a zero
> automatically by the compiler. (Just like a c-string.) (I suppose.)

Eek! No, that does not happen. You will be tricked by the fact that
your code will often work because zeros are so common, but you need to
add a final

{ 0, 0 }

entry to the table.

> So far so good.
>
> But this is not what I wrote first. I'm stepping p through each element
> in the table, so I know that eventually p points to the last element of
> the array which is a certain zero-thing. So the more natural comparison
> to me would be something like
>
> *p != NULL
>
> but the compiler won't let me because it says that *p has type
>
> struct kw,
>
> which cannot be compared with
>
> void *.
>
> %make keywords2
> cc -x c -g -std=c99 -pedantic-errors -c -o keywords2.o keywords2.c
> keywords2.c: In function ‘lookup’:
> keywords2.c:48:23: error: invalid operands to binary != (have ‘struct kw’ and ‘void *’)
> 48 | for ( p = table; *p != NULL; p++) {
> | ~~ ^~
> | |
> | struct kw
> make: *** [<builtin>: keywords2.o] Error 1
> %
>
> This makes perfect sense. But how could I detect that p has reached the
> end of the table in a more natural way than p->word? What is the
> standard way to write this? Thank you.

There is nothing wrong with using p->word. You could add a line

{ "", -1 }

and test for p->count >= 0 because any impossible value like a negative
count can be used as a sentinel (as these things are known), but using a
null pointer where a string is expected will be recognised for what it
is by everyone reading your code.

You can, just about, test for *p being "all zeros" but it's not worth
trying. For one thing structs can have padding that might be non-zero!

--
Ben.

Re: on looking up a word in a table, pointer question

<st1qka$ka3$1@dont-email.me>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=20257&group=comp.lang.c#20257

  copy link   Newsgroups: comp.lang.c
Path: i2pn2.org!i2pn.org!eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail
From: lew.pitc...@digitalfreehold.ca (Lew Pitcher)
Newsgroups: comp.lang.c
Subject: Re: on looking up a word in a table, pointer question
Date: Fri, 28 Jan 2022 22:27:22 -0000 (UTC)
Organization: A noiseless patient Spider
Lines: 145
Message-ID: <st1qka$ka3$1@dont-email.me>
References: <86k0ejbly8.fsf@levado.to>
Mime-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Injection-Date: Fri, 28 Jan 2022 22:27:22 -0000 (UTC)
Injection-Info: reader02.eternal-september.org; posting-host="f6168a9238d58af943dc6860755a6a37";
logging-data="20803"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX18zPPSCkqvqxWxWHVhp7MkEZtPR3oq92qw="
User-Agent: Pan/0.139 (Sexual Chocolate; GIT bf56508
git://git.gnome.org/pan2)
Cancel-Lock: sha1:Nm3PFsJhDbSOkuxko+gdcX46Kzk=
 by: Lew Pitcher - Fri, 28 Jan 2022 22:27 UTC

On Fri, 28 Jan 2022 18:16:15 -0300, Meredith Montgomery wrote:

> I show the full program at the end of this message, but I bet you don't
> need the full program.
>
> Here's a table of C keywords:
>
> --8<---------------cut here---------------start------------->8---
> struct kw {
> char *word;
> int count;
> };
>
> struct kw table[] = {
> {"break", 0},
> {"case", 0},
> {"char", 0},
> {"const", 0},
> {"int", 0},
> {"continue", 0},
> {"default", 0},
> {"unsigned", 0},
> {"void", 0},
> {"volatile", 0},
> {"while", 0}
> };
> --8<---------------cut here---------------end--------------->8---
>
> Here's a procedure to lookup a word in this table:
>
> --8<---------------cut here---------------start------------->8---
> struct kw * lookup(char *word, struct kw * table, int n) {
> struct kw *p;
>
> for ( p = table; p->word != NULL; p++) {
> if (strcmp(word, p->word) == 0)
> return p;
> }
>
> return NULL; /* not found */
> }
> --8<---------------cut here---------------end--------------->8---
>
> Notice how I'm stopping when p->word is not NULL. This happens when p
> gets to the last element of that array, which is terminated with a zero
> automatically by the compiler.

Nope. That just does not happen. The table you wrote terminates with the
last entry you wrote. Nothing (in that table) exists beyond that final
{"while", 0}
and the compiler /does not/ add anything (like a terminating NULL of any
sort) to the table.

> (Just like a c-string.) (I suppose.)
>
> So far so good.
>
> But this is not what I wrote first. I'm stepping p through each element
> in the table, so I know that eventually p points to the last element of
> the array which is a certain zero-thing. So the more natural comparison
> to me would be something like
>
> *p != NULL
>
> but the compiler won't let me because it says that *p has type
>
> struct kw,
>
> which cannot be compared with
>
> void *.
>
> %make keywords2 cc -x c -g -std=c99 -pedantic-errors -c -o keywords2.o
> keywords2.c keywords2.c: In function ‘lookup’:
> keywords2.c:48:23: error: invalid operands to binary != (have ‘struct
> kw’ and ‘void *’)
> 48 | for ( p = table; *p != NULL; p++) {
> | ~~ ^~
> | |
> | struct kw
> make: *** [<builtin>: keywords2.o] Error 1 %
>
> This makes perfect sense. But how could I detect that p has reached the
> end of the table in a more natural way than p->word? What is the
> standard way to write this? Thank you.

Try
for ( p = table; p < (table + sizeof table); p++) {

The expression
(table + sizeof table)
produces an object that points to the first address /after/ the end of
the table <<table>>. The C language guarantees that
[i]f both the pointer operand and the result point to elements of the
same array object, or one past the last element of the array object,
the evaluation shall not produce an overflow; otherwise, the behavior
is undefined. If the result points one past the last element of the
array object, it shall not be used as the operand of a unary * operator
that is evaluated.
In this case, the "pointer operand" is <<table>>, and the "result" points
to "one past the last element of the array object", so the expression has
a well-defined value, and will not invoke "undefined behaviour".

But, beware. You can't dereference the results of this expression:
*(table + sizeof table)
is explicitly forbidden (see the last line of the quote above).

However, you /can/ compare a pointer to the results of this expression
to determine where the pointer is in relation to the end of the table.

Specifically, while <<p>> is within the table,
p >= table
and
p < (table + sizeof table)

If <<p>> points outside the table, past the rear end (the last entry) then
p >= (table + sizeof table)
and if <<p>> points outside the table, past the front end (the first
entry) then
p < table

Now, to your loop:

<<p>> initially points to the first element of the table, so
it points at entry {"break", 0}.

With each iteration of the for() loop, the code increments <<p>> by the
length of one table entry so that it, in turn, points at each successive
entry.

With the last valid entry of the table, <<p>> points to the {"while", 0}
entry. After processing this entry, your code increments <<p>> by the
length of one table entry, so that it, now, points outside of the table.

This makes the expression
p < (table + sizeof table)
false, which terminates the loop.

[snip]

HTH
--
Lew Pitcher
"In Skills, We Trust"

Re: on looking up a word in a table, pointer question

<st1tk8$ka3$2@dont-email.me>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=20258&group=comp.lang.c#20258

  copy link   Newsgroups: comp.lang.c
Path: i2pn2.org!i2pn.org!eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail
From: lew.pitc...@digitalfreehold.ca (Lew Pitcher)
Newsgroups: comp.lang.c
Subject: Re: on looking up a word in a table, pointer question
Date: Fri, 28 Jan 2022 23:18:32 -0000 (UTC)
Organization: A noiseless patient Spider
Lines: 109
Message-ID: <st1tk8$ka3$2@dont-email.me>
References: <86k0ejbly8.fsf@levado.to> <st1qka$ka3$1@dont-email.me>
Mime-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Injection-Date: Fri, 28 Jan 2022 23:18:32 -0000 (UTC)
Injection-Info: reader02.eternal-september.org; posting-host="f96c110bc847dcf7ec8140b167891bba";
logging-data="20803"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX18FrroUmM0I3GUYHHoRPyvyB0qGc2Ba30A="
User-Agent: Pan/0.139 (Sexual Chocolate; GIT bf56508
git://git.gnome.org/pan2)
Cancel-Lock: sha1:D9JVbOyIxrtSaapN1hPaFeSPDKY=
 by: Lew Pitcher - Fri, 28 Jan 2022 23:18 UTC

On Fri, 28 Jan 2022 22:27:22 +0000, Lew Pitcher wrote:

> On Fri, 28 Jan 2022 18:16:15 -0300, Meredith Montgomery wrote:
>
>> I show the full program at the end of this message, but I bet you don't
>> need the full program.
>>
>> Here's a table of C keywords:
>>
>> --8<---------------cut here---------------start------------->8---
>> struct kw {
>> char *word;
>> int count;
>> };
>>
>> struct kw table[] = {
>> {"break", 0},
>> {"case", 0},
>> {"char", 0},
>> {"const", 0},
>> {"int", 0},
>> {"continue", 0},
>> {"default", 0},
>> {"unsigned", 0},
>> {"void", 0},
>> {"volatile", 0},
>> {"while", 0}
>> };
>> --8<---------------cut here---------------end--------------->8---
>>
>> Here's a procedure to lookup a word in this table:
>>
>> --8<---------------cut here---------------start------------->8---
>> struct kw * lookup(char *word, struct kw * table, int n) {
>> struct kw *p;
>>
>> for ( p = table; p->word != NULL; p++) {
>> if (strcmp(word, p->word) == 0)
>> return p;
>> }
>>
>> return NULL; /* not found */
>> }
>> --8<---------------cut here---------------end--------------->8---
>>
>> Notice how I'm stopping when p->word is not NULL. This happens when p
>> gets to the last element of that array, which is terminated with a zero
>> automatically by the compiler.
>
> Nope. That just does not happen. The table you wrote terminates with the
> last entry you wrote. Nothing (in that table) exists beyond that final
> {"while", 0}
> and the compiler /does not/ add anything (like a terminating NULL of any
> sort) to the table.
>
>> (Just like a c-string.) (I suppose.)
>>
>> So far so good.
>>
>> But this is not what I wrote first. I'm stepping p through each
>> element in the table, so I know that eventually p points to the last
>> element of the array which is a certain zero-thing. So the more
>> natural comparison to me would be something like
>>
>> *p != NULL
>>
>> but the compiler won't let me because it says that *p has type
>>
>> struct kw,
>>
>> which cannot be compared with
>>
>> void *.
>>
>> %make keywords2 cc -x c -g -std=c99 -pedantic-errors -c -o
>> keywords2.o keywords2.c keywords2.c: In function ‘lookup’:
>> keywords2.c:48:23: error: invalid operands to binary != (have ‘struct
>> kw’ and ‘void *’)
>> 48 | for ( p = table; *p != NULL; p++) {
>> | ~~ ^~
>> | |
>> | struct kw
>> make: *** [<builtin>: keywords2.o] Error 1 %
>>
>> This makes perfect sense. But how could I detect that p has reached
>> the end of the table in a more natural way than p->word? What is the
>> standard way to write this? Thank you.
>
> Try
> for ( p = table; p < (table + sizeof table); p++) {

Gawd, I shouldn't post on an empty stomach. And, I'm too used to using
char pointers that I forgot about array entry length computations.
(Excuses, excuses... mea culpa)

I meant
for ( p = table; p < (struct kw *)((char *)table + sizeof table); p++) {
because
1) pointers increment by the size of the thing they are pointing to
so, here, we have to make (table + sizeof table) increment in
char rather than struct kw, so we coerce <<table>> into char
2) pointers compare to pointers of the same type, so we must coerce
the results of ((char *)table + sizeof table) /back/ into a
struct kw * before we compare to <<p>>

Yah. I'll shut up now.
--
Lew Pitcher
"In Skills, We Trust"

Re: on looking up a word in a table, pointer question

<st1tug$1lig$1@gioia.aioe.org>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=20260&group=comp.lang.c#20260

  copy link   Newsgroups: comp.lang.c
Path: i2pn2.org!i2pn.org!aioe.org!CC3uK9WYEoa7s1kzH7komw.user.46.165.242.75.POSTED!not-for-mail
From: news.dea...@darjeeling.plus.com (Mike Terry)
Newsgroups: comp.lang.c
Subject: Re: on looking up a word in a table, pointer question
Date: Fri, 28 Jan 2022 23:23:59 +0000
Organization: Aioe.org NNTP Server
Message-ID: <st1tug$1lig$1@gioia.aioe.org>
References: <86k0ejbly8.fsf@levado.to> <st1qka$ka3$1@dont-email.me>
Mime-Version: 1.0
Content-Type: text/plain; charset=windows-1252; format=flowed
Content-Transfer-Encoding: 8bit
Injection-Info: gioia.aioe.org; logging-data="54864"; posting-host="CC3uK9WYEoa7s1kzH7komw.user.gioia.aioe.org"; mail-complaints-to="abuse@aioe.org";
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:60.0) Gecko/20100101
Firefox/60.0 SeaMonkey/2.53.7.1
X-Notice: Filtered by postfilter v. 0.9.2
 by: Mike Terry - Fri, 28 Jan 2022 23:23 UTC

On 28/01/2022 22:27, Lew Pitcher wrote:
> On Fri, 28 Jan 2022 18:16:15 -0300, Meredith Montgomery wrote:
>
>> I show the full program at the end of this message, but I bet you don't
>> need the full program.
>>
>> Here's a table of C keywords:
>>
>> --8<---------------cut here---------------start------------->8---
>> struct kw {
>> char *word;
>> int count;
>> };
>>
>> struct kw table[] = {
>> {"break", 0},
>> {"case", 0},
>> {"char", 0},
>> {"const", 0},
>> {"int", 0},
>> {"continue", 0},
>> {"default", 0},
>> {"unsigned", 0},
>> {"void", 0},
>> {"volatile", 0},
>> {"while", 0}
>> };
>> --8<---------------cut here---------------end--------------->8---
>>
>> Here's a procedure to lookup a word in this table:
>>
>> --8<---------------cut here---------------start------------->8---
>> struct kw * lookup(char *word, struct kw * table, int n) {
>> struct kw *p;
>>
>> for ( p = table; p->word != NULL; p++) {
>> if (strcmp(word, p->word) == 0)
>> return p;
>> }
>>
>> return NULL; /* not found */
>> }
>> --8<---------------cut here---------------end--------------->8---
>>
>> Notice how I'm stopping when p->word is not NULL. This happens when p
>> gets to the last element of that array, which is terminated with a zero
>> automatically by the compiler.
>
> Nope. That just does not happen. The table you wrote terminates with the
> last entry you wrote. Nothing (in that table) exists beyond that final
> {"while", 0}
> and the compiler /does not/ add anything (like a terminating NULL of any
> sort) to the table.
>
>> (Just like a c-string.) (I suppose.)
>>
>> So far so good.
>>
>> But this is not what I wrote first. I'm stepping p through each element
>> in the table, so I know that eventually p points to the last element of
>> the array which is a certain zero-thing. So the more natural comparison
>> to me would be something like
>>
>> *p != NULL
>>
>> but the compiler won't let me because it says that *p has type
>>
>> struct kw,
>>
>> which cannot be compared with
>>
>> void *.
>>
>> %make keywords2 cc -x c -g -std=c99 -pedantic-errors -c -o keywords2.o
>> keywords2.c keywords2.c: In function ‘lookup’:
>> keywords2.c:48:23: error: invalid operands to binary != (have ‘struct
>> kw’ and ‘void *’)
>> 48 | for ( p = table; *p != NULL; p++) {
>> | ~~ ^~
>> | |
>> | struct kw
>> make: *** [<builtin>: keywords2.o] Error 1 %
>>
>> This makes perfect sense. But how could I detect that p has reached the
>> end of the table in a more natural way than p->word? What is the
>> standard way to write this? Thank you.
>
> Try
> for ( p = table; p < (table + sizeof table); p++) {
>
> The expression
> (table + sizeof table)
> produces an object that points to the first address /after/ the end of
> the table <<table>>.

That's not right. table is a pointer, so sizeof table is the length of a pointer, probably 4 or 8.

Also, adding say 4 to a pointer does not increase the memory address in the pointer by 4. The
address will increase by the size of 4 ENTRIES of the size of the table entries. I.e. when adding
to a pointer, the value added represents THE NUMBER OF ENTRIES of the pointed-to table by which you
are advancing the pointer.

So your code would just process a fixed number of entries (probably 4 or 8) regardless of the actual
size of the table.

Probably you were thinking table was an array, not a pointer. But that would still be wrong,
because then "sizeof table" would be the MEMORY SIZE of the table, not the number of entries in the
table. What you would actually need for this scenario is
for ( p = table; p < (table + sizeof table / sizeof table[0]); p++) {
...

For Lew, if you have a function which is passed a pointer to a table of data, there are only really
two options: the number of entries in the table can be explicitly passed to the function as another
parameter, or you can ensure there is some way to recognise the last entry in the table - that means
using some "out of normal range" value in the table entry, as Ben suggested. (Both approaches are
common.)

Some advice - if documenting a function that receives a "length" field as a parameter, be clear what
the length means: is it a "number of bytes" length or a "count of entries" length? Early Microsoft
API documentation had numerous instances where this was either not clear, or worse on occasions it
was clear but wrong!

Mike.

> The C language guarantees that
> [i]f both the pointer operand and the result point to elements of the
> same array object, or one past the last element of the array object,
> the evaluation shall not produce an overflow; otherwise, the behavior
> is undefined. If the result points one past the last element of the
> array object, it shall not be used as the operand of a unary * operator
> that is evaluated.
> In this case, the "pointer operand" is <<table>>, and the "result" points
> to "one past the last element of the array object", so the expression has
> a well-defined value, and will not invoke "undefined behaviour".
>
> But, beware. You can't dereference the results of this expression:
> *(table + sizeof table)
> is explicitly forbidden (see the last line of the quote above).
>
> However, you /can/ compare a pointer to the results of this expression
> to determine where the pointer is in relation to the end of the table.
>
> Specifically, while <<p>> is within the table,
> p >= table
> and
> p < (table + sizeof table)
>
> If <<p>> points outside the table, past the rear end (the last entry) then
> p >= (table + sizeof table)
> and if <<p>> points outside the table, past the front end (the first
> entry) then
> p < table
>
> Now, to your loop:
>
> <<p>> initially points to the first element of the table, so
> it points at entry {"break", 0}.
>
> With each iteration of the for() loop, the code increments <<p>> by the
> length of one table entry so that it, in turn, points at each successive
> entry.
>
> With the last valid entry of the table, <<p>> points to the {"while", 0}
> entry. After processing this entry, your code increments <<p>> by the
> length of one table entry, so that it, now, points outside of the table.
>
> This makes the expression
> p < (table + sizeof table)
> false, which terminates the loop.
>
>
> [snip]
>
> HTH
>

Re: on looking up a word in a table, pointer question

<86ilu39wul.fsf@levado.to>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=20263&group=comp.lang.c#20263

  copy link   Newsgroups: comp.lang.c
Path: i2pn2.org!i2pn.org!aioe.org!SZor4ZqbvgPVVsWQ21e4cw.user.46.165.242.75.POSTED!not-for-mail
From: mmontgom...@levado.to (Meredith Montgomery)
Newsgroups: comp.lang.c
Subject: Re: on looking up a word in a table, pointer question
Date: Fri, 28 Jan 2022 22:03:46 -0300
Organization: Aioe.org NNTP Server
Message-ID: <86ilu39wul.fsf@levado.to>
References: <86k0ejbly8.fsf@levado.to> <20220128135506.266@kylheku.com>
Mime-Version: 1.0
Content-Type: text/plain
Injection-Info: gioia.aioe.org; logging-data="51987"; posting-host="SZor4ZqbvgPVVsWQ21e4cw.user.gioia.aioe.org"; mail-complaints-to="abuse@aioe.org";
Cancel-Lock: sha1:AyyJP80N7vz8CBVQ9RVX9UPnw8Y=
X-Notice: Filtered by postfilter v. 0.9.2
 by: Meredith Montgomery - Sat, 29 Jan 2022 01:03 UTC

Kaz Kylheku <480-992-1380@kylheku.com> writes:

> On 2022-01-28, Meredith Montgomery <mmontgomery@levado.to> wrote:
>> I show the full program at the end of this message, but I bet you don't
>> need the full program.
>>
>> Here's a table of C keywords:
>>
>> --8<---------------cut here---------------start------------->8---
>> struct kw {
>> char *word;
>> int count;
>> };
>>
>> struct kw table[] = {
>> {"break", 0},
>> {"case", 0},
>> {"char", 0},
>> {"const", 0},
>> {"int", 0},
>> {"continue", 0},
>> {"default", 0},
>> {"unsigned", 0},
>> {"void", 0},
>> {"volatile", 0},
>> {"while", 0}
>> };
>> --8<---------------cut here---------------end--------------->8---
>>
>> Here's a procedure to lookup a word in this table:
>>
>> --8<---------------cut here---------------start------------->8---
>> struct kw * lookup(char *word, struct kw * table, int n) {
>> struct kw *p;
>>
>> for ( p = table; p->word != NULL; p++) {
>> if (strcmp(word, p->word) == 0)
>> return p;
>> }
>>
>> return NULL; /* not found */
>> }
>> --8<---------------cut here---------------end--------------->8---
>>
>> Notice how I'm stopping when p->word is not NULL.
>
> So you need an entry for that in the array
>
> {"while", 0},
> {NULL, 0}
> };

Aha! That's what I had not realized.

>> };
>> This happens when p gets to the last element.
>
> "gets" is deprecated in C, please say "moves" or "mosies on over to" or
> some other more precise word. :)

Lol. Will do. :-)

>> to the last element of that array, which is terminated with a zero
>> automatically by the compiler. (Just like a c-string.) (I suppose.)
>>
>> So far so good.
>>
>> But this is not what I wrote first. I'm stepping p through each element
>> in the table, so I know that eventually p points to the last element of
>> the array which is a certain zero-thing.
>
> The last element of the array is the {"while", 0} entry.

Yes, I was bitten there. Thanks for pointing it out.

> So the more natural comparison
>> to me would be something like
>>
>> *p != NULL
>>
>> but the compiler won't let me because it says that *p has type
>>
>> struct kw,
>>
>> which cannot be compared with
>>
>> void *.
>
> That could be arrangd, but provides no benefit:
>
> int null_kw(struct kw kw)
> {
> return kw.word == NULL && kw.count == 0;
> }
>
> So then, provided you have the {NULL, 0} entry in the table. the loop
> could terminate like this:
>
> for (p = table; !null_kw(*p); p++)

Lol. I've done this once. Lol. It's really such a bad solution. Let
me see if I can look up when I did this. Here.

typedef struct Pair {
uint64_t p;
uint64_t q;
} Pair;

#define IS_NOT_NIL_PAIR(P) (P.p != 0 && P.q != 0)

int main() {
Pair N;
for (N = composites(); IS_NOT_NIL_PAIR(N); N = composites()) {
printf("Pair (%ld, %ld) produces N = %ld\n", N.p, N.q, N.p * N.q);
}
printf("Done\n");
return 0;
}

Pair composites(void) {
static unsigned int i = 0;
static unsigned int j = 1;

Pair N;
N.p = primes(i);
N.q = primes(j);

if (i == (primes_size() - 1) && j == primes_size()) {
return (Pair) {0, 0};
}

j = j + 1;

if (j == (primes_size())) {
i = i + 1;
j = i + 1;
}

return N;
}

Oh, boy. I really didn't know any better at that time.

My case up there wasn't quite a table, but I wanted to somehow specify
that at some point I wasn't going to generate more composites and,
because I didn't want to work with pointers, I had to return a struct.
I guess I still don't know how to do any better here. (It's not a
table.)

I think I should improve this a by creating a nullPair --- like Kaz
Kylheku was doing. So in case of termination or error, I just return
this nullPair.

[...]

Re: on looking up a word in a table, pointer question

<86a6ff9ws7.fsf@levado.to>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=20264&group=comp.lang.c#20264

  copy link   Newsgroups: comp.lang.c
Path: i2pn2.org!i2pn.org!aioe.org!SZor4ZqbvgPVVsWQ21e4cw.user.46.165.242.75.POSTED!not-for-mail
From: mmontgom...@levado.to (Meredith Montgomery)
Newsgroups: comp.lang.c
Subject: Re: on looking up a word in a table, pointer question
Date: Fri, 28 Jan 2022 22:05:12 -0300
Organization: Aioe.org NNTP Server
Message-ID: <86a6ff9ws7.fsf@levado.to>
References: <86k0ejbly8.fsf@levado.to> <87h79nzehy.fsf@bsb.me.uk>
Mime-Version: 1.0
Content-Type: text/plain
Injection-Info: gioia.aioe.org; logging-data="51987"; posting-host="SZor4ZqbvgPVVsWQ21e4cw.user.gioia.aioe.org"; mail-complaints-to="abuse@aioe.org";
X-Notice: Filtered by postfilter v. 0.9.2
Cancel-Lock: sha1:tB15QjIsKDmlLX6CgSRx7yxPbVg=
 by: Meredith Montgomery - Sat, 29 Jan 2022 01:05 UTC

Ben Bacarisse <ben.usenet@bsb.me.uk> writes:

> Meredith Montgomery <mmontgomery@levado.to> writes:
>
>> I show the full program at the end of this message, but I bet you don't
>> need the full program.
>>
>> Here's a table of C keywords:
>>
>> struct kw {
>> char *word;
>> int count;
>> };
>>
>> struct kw table[] = {
>> {"break", 0},
>> {"case", 0},
>> {"char", 0},
>> {"const", 0},
>> {"int", 0},
>> {"continue", 0},
>> {"default", 0},
>> {"unsigned", 0},
>> {"void", 0},
>> {"volatile", 0},
>> {"while", 0}
>> };
>>
>>
>> Here's a procedure to lookup a word in this table:
>>
>> struct kw * lookup(char *word, struct kw * table, int n) {
>> struct kw *p;
>>
>> for ( p = table; p->word != NULL; p++) {
>> if (strcmp(word, p->word) == 0)
>> return p;
>> }
>>
>> return NULL; /* not found */
>> }
>>
>> Notice how I'm stopping when p->word is not NULL. This happens when p
>> gets to the last element of that array, which is terminated with a zero
>> automatically by the compiler. (Just like a c-string.) (I suppose.)
>
> Eek! No, that does not happen. You will be tricked by the fact that
> your code will often work because zeros are so common, but you need to
> add a final
>
> { 0, 0 }
>
> entry to the table.

That's right. Lesson learned!

Re: on looking up a word in a table, pointer question

<st27nh$gnb$1@dont-email.me>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=20268&group=comp.lang.c#20268

  copy link   Newsgroups: comp.lang.c
Path: i2pn2.org!i2pn.org!eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail
From: jameskuy...@alumni.caltech.edu (James Kuyper)
Newsgroups: comp.lang.c
Subject: Re: on looking up a word in a table, pointer question
Date: Fri, 28 Jan 2022 21:10:57 -0500
Organization: A noiseless patient Spider
Lines: 40
Message-ID: <st27nh$gnb$1@dont-email.me>
References: <86k0ejbly8.fsf@levado.to> <87h79nzehy.fsf@bsb.me.uk>
Mime-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 7bit
Injection-Date: Sat, 29 Jan 2022 02:10:57 -0000 (UTC)
Injection-Info: reader02.eternal-september.org; posting-host="ec161bfa19ec8c044acf5537a2d99725";
logging-data="17131"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX19gwAIIzSJOtb432jaN5b2nkYHqAwscMFE="
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101
Thunderbird/91.5.0
Cancel-Lock: sha1:fNwiprYoqB9bXW+UujT66tj9dFs=
In-Reply-To: <87h79nzehy.fsf@bsb.me.uk>
Content-Language: en-US
 by: James Kuyper - Sat, 29 Jan 2022 02:10 UTC

On 1/28/22 17:23, Ben Bacarisse wrote:
> Meredith Montgomery <mmontgomery@levado.to> writes:
....
>> struct kw {
>> char *word; int count;
>> };
>>
>> struct kw table[] = {
>> {"break", 0},
>> {"case", 0},
>> {"char", 0},
>> {"const", 0},
>> {"int", 0},
>> {"continue", 0},
>> {"default", 0},
>> {"unsigned", 0},
>> {"void", 0},
>> {"volatile", 0},
>> {"while", 0}
>> };
....
>> Notice how I'm stopping when p->word is not NULL. This happens when p
>> gets to the last element of that array, which is terminated with a zero
>> automatically by the compiler. (Just like a c-string.) (I suppose.)
>
> Eek! No, that does not happen. You will be tricked by the fact that
> your code will often work because zeros are so common, but you need to
> add a final
>
> { 0, 0 }

Note, however, that something similar can happen. If he had specified
that table has 12 or more elements, "all subobjects that are not
initialized explicitly shall be initialized implicitly the same as
objects that have static storage duration." (6.7.9p19). For pointers,
that means a null pointer (6.7.9p10).

Of course, explicitly adding a {0,0} at the end is a better solution, as
it works regardless of the number of initializers.

Re: on looking up a word in a table, pointer question

<87pmobxoek.fsf@bsb.me.uk>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=20270&group=comp.lang.c#20270

  copy link   Newsgroups: comp.lang.c
Path: i2pn2.org!i2pn.org!eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail
From: ben.use...@bsb.me.uk (Ben Bacarisse)
Newsgroups: comp.lang.c
Subject: Re: on looking up a word in a table, pointer question
Date: Sat, 29 Jan 2022 02:32:19 +0000
Organization: A noiseless patient Spider
Lines: 54
Message-ID: <87pmobxoek.fsf@bsb.me.uk>
References: <86k0ejbly8.fsf@levado.to> <st1qka$ka3$1@dont-email.me>
<st1tk8$ka3$2@dont-email.me>
Mime-Version: 1.0
Content-Type: text/plain
Injection-Info: reader02.eternal-september.org; posting-host="00be0330ed62b735868e93f7a4aba188";
logging-data="26812"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX19MJpamccOff8O1HmQFCMinIMoQyVgQQg8="
Cancel-Lock: sha1:CaI7haWlQHrC3S2hIJkhvOv51Kg=
sha1:KKutElZz256ZJJqW+hi0F1azqzg=
X-BSB-Auth: 1.aa9897eec5a370e1af9c.20220129023219GMT.87pmobxoek.fsf@bsb.me.uk
 by: Ben Bacarisse - Sat, 29 Jan 2022 02:32 UTC

Lew Pitcher <lew.pitcher@digitalfreehold.ca> writes:

> On Fri, 28 Jan 2022 22:27:22 +0000, Lew Pitcher wrote:
>
>> On Fri, 28 Jan 2022 18:16:15 -0300, Meredith Montgomery wrote:

>>> struct kw * lookup(char *word, struct kw * table, int n) {
>>> struct kw *p;
>>>
>>> for ( p = table; p->word != NULL; p++) {
>>> if (strcmp(word, p->word) == 0)
>>> return p;
>>> }
>>>
>>> return NULL; /* not found */
>>> }

> Gawd, I shouldn't post on an empty stomach. And, I'm too used to using
> char pointers that I forgot about array entry length computations.
> (Excuses, excuses... mea culpa)
>
> I meant
> for ( p = table; p < (struct kw *)((char *)table + sizeof table); p++) {
> because
> 1) pointers increment by the size of the thing they are pointing to
> so, here, we have to make (table + sizeof table) increment in
> char rather than struct kw, so we coerce <<table>> into char
> 2) pointers compare to pointers of the same type, so we must coerce
> the results of ((char *)table + sizeof table) /back/ into a
> struct kw * before we compare to <<p>>

But, as has been pointed out, table is a pointer here, not an array, so
sizeof table is of no use at all, no matter how you scale it.

However, when you really /do/ have an array called table, the usual way
to get its size is to write sizeof table / sizeof *table. That's
clearer, in my opinion, than casting pointer types.

Second however, since I'm a bit odd, I would write (&table)[1] to get a
pointer just past the end of the array:

for (struct kw *p = table; p < (&table)[1]; p++) ...

To the OP: remember, this does not work inside a function where you
have a pointer to the first element, rather than an array proper: table
is the name of an array outside the lookup function, but it's a pointer
inside it.

I've been caught out by this, so I always avoid parameter names that
shadow array names. gcc even has a warning you can turn on for this,
though it is more general than I'd like.

--
Ben.

Re: on looking up a word in a table, pointer question

<86k0eh4ash.fsf@levado.to>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=20299&group=comp.lang.c#20299

  copy link   Newsgroups: comp.lang.c
Path: i2pn2.org!i2pn.org!aioe.org!swDOntj3lPshdK/dkw97wQ.user.46.165.242.75.POSTED!not-for-mail
From: mmontgom...@levado.to (Meredith Montgomery)
Newsgroups: comp.lang.c
Subject: Re: on looking up a word in a table, pointer question
Date: Sun, 30 Jan 2022 10:23:42 -0300
Organization: Aioe.org NNTP Server
Message-ID: <86k0eh4ash.fsf@levado.to>
References: <86k0ejbly8.fsf@levado.to> <st1qka$ka3$1@dont-email.me>
<st1tk8$ka3$2@dont-email.me> <87pmobxoek.fsf@bsb.me.uk>
Mime-Version: 1.0
Content-Type: text/plain
Injection-Info: gioia.aioe.org; logging-data="47894"; posting-host="swDOntj3lPshdK/dkw97wQ.user.gioia.aioe.org"; mail-complaints-to="abuse@aioe.org";
Cancel-Lock: sha1:ZWa+ARUQuH+Rzrn5yu81vtel1kE=
X-Notice: Filtered by postfilter v. 0.9.2
 by: Meredith Montgomery - Sun, 30 Jan 2022 13:23 UTC

Ben Bacarisse <ben.usenet@bsb.me.uk> writes:

> Lew Pitcher <lew.pitcher@digitalfreehold.ca> writes:
>
>> On Fri, 28 Jan 2022 22:27:22 +0000, Lew Pitcher wrote:
>>
>>> On Fri, 28 Jan 2022 18:16:15 -0300, Meredith Montgomery wrote:
>
>>>> struct kw * lookup(char *word, struct kw * table, int n) {
>>>> struct kw *p;
>>>>
>>>> for ( p = table; p->word != NULL; p++) {
>>>> if (strcmp(word, p->word) == 0)
>>>> return p;
>>>> }
>>>>
>>>> return NULL; /* not found */
>>>> }
>
>> Gawd, I shouldn't post on an empty stomach. And, I'm too used to using
>> char pointers that I forgot about array entry length computations.
>> (Excuses, excuses... mea culpa)
>>
>> I meant
>> for ( p = table; p < (struct kw *)((char *)table + sizeof table); p++) {
>> because
>> 1) pointers increment by the size of the thing they are pointing to
>> so, here, we have to make (table + sizeof table) increment in
>> char rather than struct kw, so we coerce <<table>> into char
>> 2) pointers compare to pointers of the same type, so we must coerce
>> the results of ((char *)table + sizeof table) /back/ into a
>> struct kw * before we compare to <<p>>
>
> But, as has been pointed out, table is a pointer here, not an array, so
> sizeof table is of no use at all, no matter how you scale it.
>
> However, when you really /do/ have an array called table, the usual way
> to get its size is to write sizeof table / sizeof *table. That's
> clearer, in my opinion, than casting pointer types.
>
> Second however, since I'm a bit odd, I would write (&table)[1] to get a
> pointer just past the end of the array:
>
> for (struct kw *p = table; p < (&table)[1]; p++) ...

You taught me this already in previous threads --- one where I had a
pointer to an array of 13 chars. (You showed this solution then. I
then commented on the terminology of ``end of the array''.) I was
bitten there that by adding one to that pointer it advanced 13 chars and
I couldn't see why. The lesson there was that a pointer has a type that
must be noticed. Pointer arithmetic is dependent upon the type of the
pointer. My intuition of what a pointer is improved immensely.

> To the OP: remember, this does not work inside a function where you
> have a pointer to the first element, rather than an array proper: table
> is the name of an array outside the lookup function, but it's a pointer
> inside it.

That's right --- I was bitten by that in this case. The macro

#define NKEYS ((sizeof table) / (sizeof table[0]))

happens to do 8/16 == 0 in that procedure where table is a pointer.
That /struct kw/ happens to occupy 16 bytes in my system. Alignment
reasons, I suppose. The members themselves should occupy 8 + 4 bytes
in my system because I have a pointer to char and an int.

struct kw {
char *word;
int count;
};

> I've been caught out by this, so I always avoid parameter names that
> shadow array names. gcc even has a warning you can turn on for this,
> though it is more general than I'd like.

I might just start doing the same because I did fall for the same and it
probably took me over an hour to realize the trouble. (Learning
immensely lately.)

Re: on looking up a word in a table, pointer question

<st64op$su5$1@dont-email.me>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=20300&group=comp.lang.c#20300

  copy link   Newsgroups: comp.lang.c
Path: i2pn2.org!i2pn.org!eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail
From: bc...@freeuk.com (Bart)
Newsgroups: comp.lang.c
Subject: Re: on looking up a word in a table, pointer question
Date: Sun, 30 Jan 2022 13:44:57 +0000
Organization: A noiseless patient Spider
Lines: 89
Message-ID: <st64op$su5$1@dont-email.me>
References: <86k0ejbly8.fsf@levado.to> <st1qka$ka3$1@dont-email.me>
<st1tk8$ka3$2@dont-email.me> <87pmobxoek.fsf@bsb.me.uk>
<86k0eh4ash.fsf@levado.to>
Mime-Version: 1.0
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 7bit
Injection-Date: Sun, 30 Jan 2022 13:44:57 -0000 (UTC)
Injection-Info: reader02.eternal-september.org; posting-host="f27f296bb7e2256613f390f358a9e846";
logging-data="29637"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1+A43zPXY76x2Jf4MvnGugJpuFUw2HGAgU="
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:91.0) Gecko/20100101
Thunderbird/91.5.0
Cancel-Lock: sha1:RCCXwhbBb5xu6xYWcRFvTU9TSKI=
In-Reply-To: <86k0eh4ash.fsf@levado.to>
 by: Bart - Sun, 30 Jan 2022 13:44 UTC

On 30/01/2022 13:23, Meredith Montgomery wrote:
> Ben Bacarisse <ben.usenet@bsb.me.uk> writes:
>
>> Lew Pitcher <lew.pitcher@digitalfreehold.ca> writes:
>>
>>> On Fri, 28 Jan 2022 22:27:22 +0000, Lew Pitcher wrote:
>>>
>>>> On Fri, 28 Jan 2022 18:16:15 -0300, Meredith Montgomery wrote:
>>
>>>>> struct kw * lookup(char *word, struct kw * table, int n) {
>>>>> struct kw *p;
>>>>>
>>>>> for ( p = table; p->word != NULL; p++) {
>>>>> if (strcmp(word, p->word) == 0)
>>>>> return p;
>>>>> }
>>>>>
>>>>> return NULL; /* not found */
>>>>> }
>>
>>> Gawd, I shouldn't post on an empty stomach. And, I'm too used to using
>>> char pointers that I forgot about array entry length computations.
>>> (Excuses, excuses... mea culpa)
>>>
>>> I meant
>>> for ( p = table; p < (struct kw *)((char *)table + sizeof table); p++) {
>>> because
>>> 1) pointers increment by the size of the thing they are pointing to
>>> so, here, we have to make (table + sizeof table) increment in
>>> char rather than struct kw, so we coerce <<table>> into char
>>> 2) pointers compare to pointers of the same type, so we must coerce
>>> the results of ((char *)table + sizeof table) /back/ into a
>>> struct kw * before we compare to <<p>>
>>
>> But, as has been pointed out, table is a pointer here, not an array, so
>> sizeof table is of no use at all, no matter how you scale it.
>>
>> However, when you really /do/ have an array called table, the usual way
>> to get its size is to write sizeof table / sizeof *table. That's
>> clearer, in my opinion, than casting pointer types.
>>
>> Second however, since I'm a bit odd, I would write (&table)[1] to get a
>> pointer just past the end of the array:
>>
>> for (struct kw *p = table; p < (&table)[1]; p++) ...
>
> You taught me this already in previous threads --- one where I had a
> pointer to an array of 13 chars. (You showed this solution then. I
> then commented on the terminology of ``end of the array''.) I was
> bitten there that by adding one to that pointer it advanced 13 chars and
> I couldn't see why.

It /is/ difficult to see why. I believe that if you have to stop and
think about something, then you ought to find a different way of doing
it. Others may be confused too.

Or at least, use a macro:

#define ENDOF(table) ((&table)[1]) // address of last+1 element

Then it can be used like this:

#include <stdio.h>

int main(void) {
int table[] = {10,20,30,40};

for (int* p = table; p < ENDOF(table); ++p) {
printf("%d\n", *p);
}
}

Although I would personally avoid one past the last element business,
and do it like this:

#define ENDOF(table) (&table[(sizeof(table)/sizeof(table[0])-1)])

int main(void) {
int table[] = {10,20,30,40};

for (int* p = table; p <= ENDOF(table); ++p) {
printf("%d\n", *p);
}
}

Now ENDOF is the actual last element, not the following one. (This
requires 'table' to be a proper, dimensioned array; probably the first
does too, but that's harder to see.)

1
server_pubkey.txt

rocksolid light 0.9.8
clearnet tor