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


Groups > comp.std.c > #6570 > unrolled thread

why can change element of a const typed struct ?

Started byDenis Dos Santos Silva <denis@roo.com.br>
First post2023-09-18 08:49 -0700
Last post2023-09-18 20:13 +0100
Articles 5 — 3 participants

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


Contents

  why can change element of a const typed struct ? Denis Dos Santos Silva <denis@roo.com.br> - 2023-09-18 08:49 -0700
    Re: why can change element of a const typed struct ? David Brown <david.brown@hesbynett.no> - 2023-09-18 20:29 +0200
      Re: why can change element of a const typed struct ? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2023-09-18 20:58 +0100
        Re: why can change element of a const typed struct ? David Brown <david.brown@hesbynett.no> - 2023-09-19 17:15 +0200
    Re: why can change element of a const typed struct ? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2023-09-18 20:13 +0100

#6570 — why can change element of a const typed struct ?

FromDenis Dos Santos Silva <denis@roo.com.br>
Date2023-09-18 08:49 -0700
Subjectwhy can change element of a const typed struct ?
Message-ID<6d826a46-8852-4aa3-9e7d-23fac761e840n@googlegroups.com>
hi all!
why this works? =)



/// image.c 
/// ...
typedef struct {
	int w;
	int h;
	unsigned char channels;
	unsigned char *data;
	int err;
} image_t;

int image_copy(const image_t* source, const image_t* target, int xoffset, int yoffset) {
	register int sindex;
	register int tindex = 0;
	register int y1, x1;

	if (!source || !target)
		return -1;

	for (int y=0; y<target->h; y++) {
		for (int x=0; x<target->w; x++) {
			#if 1
			y1		= y+yoffset;
			x1		= x+xoffset;

			sindex	= (y1 * source->w + x1) * 3;
			if (sindex > (source->w * source->h * 3))
				continue;

// change value of element of const struct

			source->data[sindex+0] = target->data[tindex++];
			source->data[sindex+1] = target->data[tindex++];
			source->data[sindex+2] = target->data[tindex++];
			#endif
		}
	}

	return 0;
}
/// <eof>

[toc] | [next] | [standalone]


#6571

FromDavid Brown <david.brown@hesbynett.no>
Date2023-09-18 20:29 +0200
Message-ID<uea4ti$1stu4$1@dont-email.me>
In reply to#6570
On 18/09/2023 17:49, Denis Dos Santos Silva wrote:
> hi all!
> why this works? =)
> 

Your image_t is const, but it has a non-const pointer "data" - there is 
no restriction to accessing the elements pointed to by source->data.

So your function can't change "source->data", but it /can/ change 
"source->data[sindex]".

"const" does not pass through layers of pointers, it only applies to the 
first pointed-at layer.

Does that help?

> 
> 
> /// image.c
> /// ...
> typedef struct {
> 	int w;
> 	int h;
> 	unsigned char channels;
> 	unsigned char *data;
> 	int err;
> } image_t;
> 
> int image_copy(const image_t* source, const image_t* target, int xoffset, int yoffset) {
> 	register int sindex;
> 	register int tindex = 0;
> 	register int y1, x1;
> 
> 	if (!source || !target)
> 		return -1;
> 
> 	for (int y=0; y<target->h; y++) {
> 		for (int x=0; x<target->w; x++) {
> 			#if 1
> 			y1		= y+yoffset;
> 			x1		= x+xoffset;
> 
> 			sindex	= (y1 * source->w + x1) * 3;
> 			if (sindex > (source->w * source->h * 3))
> 				continue;
> 
> // change value of element of const struct
> 
> 			source->data[sindex+0] = target->data[tindex++];
> 			source->data[sindex+1] = target->data[tindex++];
> 			source->data[sindex+2] = target->data[tindex++];
> 			#endif
> 		}
> 	}
> 
> 	return 0;
> }
> /// <eof>

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


#6573

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2023-09-18 20:58 +0100
Message-ID<871qevjls3.fsf@bsb.me.uk>
In reply to#6571
David Brown <david.brown@hesbynett.no> writes:

> On 18/09/2023 17:49, Denis Dos Santos Silva wrote:
>> hi all!
>> why this works? =)
>
> Your image_t is const, but it has a non-const pointer "data" - there is no
> restriction to accessing the elements pointed to by source->data.

I feel I must quibble because it can matter to someone learning C.

When accessed via 'const image_t *source', data /is/ (treated as) const.
data is a pointer, and the lvalue expression source->data is const
qualified.  To call it a "non-const pointer" is using a common
shorthand, but one I've found is very confusing to beginners.

We casually talk about "const pointers" and "non-const pointers" because
we all know what we mean, but people learning C can get confused by what
is and is not const-qualified.  It's a handy shorthand because an actual
'const pointer' is not seen so often:

  char *const endp = start + strlen(start);

But we often see this

  const char *end = start + strlen(start);

described as a const pointer even though changing the pointer is
perfectly valid:

  end -= 1;  // permitted because end is pointer that is not const

> So your function can't change "source->data",

Right, because data is treated as a const pointer.  Calling it a
non-const pointer is potentially confusing.  I know what you meant, but
is it clear to everyone?

> but it /can/ change "source->data[sindex]".
>
> "const" does not pass through layers of pointers, it only applies to the
> first pointed-at layer.

Your remark suggests that there is something special about one level of
indirection, but there isn't.

-- 
Ben.

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


#6574

FromDavid Brown <david.brown@hesbynett.no>
Date2023-09-19 17:15 +0200
Message-ID<uecduj$2dcj7$1@dont-email.me>
In reply to#6573
On 18/09/2023 21:58, Ben Bacarisse wrote:
> David Brown <david.brown@hesbynett.no> writes:
> 
>> On 18/09/2023 17:49, Denis Dos Santos Silva wrote:
>>> hi all!
>>> why this works? =)
>>
>> Your image_t is const, but it has a non-const pointer "data" - there is no
>> restriction to accessing the elements pointed to by source->data.
> 
> I feel I must quibble because it can matter to someone learning C.
> 
> When accessed via 'const image_t *source', data /is/ (treated as) const.
> data is a pointer, and the lvalue expression source->data is const
> qualified.  To call it a "non-const pointer" is using a common
> shorthand, but one I've found is very confusing to beginners.
> 
> We casually talk about "const pointers" and "non-const pointers" because
> we all know what we mean, but people learning C can get confused by what
> is and is not const-qualified.  It's a handy shorthand because an actual
> 'const pointer' is not seen so often:
> 

Those are very good points, and I am glad you gave a better and more 
accurate explanation than I did.


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


#6572

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2023-09-18 20:13 +0100
Message-ID<87cyyfjnvl.fsf@bsb.me.uk>
In reply to#6570
Denis Dos Santos Silva <denis@roo.com.br> writes:

> hi all!

This would probably be better sent to comp.lang.c so I am setting the
followup-to header accordingly.  This group is mainly about the ISO C
standard, though it's possible you are asking why the standard permits
this.

> why this works? =)
(from subject) why can change element of a const typed struct ?

Short answer: you are not changing any member of the struct.  The
constness of the target of the pointer does transfer to other pointers
in the struct.  data is const, but data[x] is not.

A detail...  the struct is not const (well, it might be, but we can't
tell from this code).  The struct is being accessed via pointer whose
target type is const.  Now that would indeed require a diagnostic if the
code tried to change any of the members, but it does not.

> /// image.c 
> /// ...
> typedef struct {
> 	int w;
> 	int h;
> 	unsigned char channels;
> 	unsigned char *data;
> 	int err;
> } image_t;
>
> int image_copy(const image_t* source, const image_t* target, int
> xoffset, int yoffset) {
...
> 			source->data[sindex+0] = target->data[tindex++];
> 			source->data[sindex+1] = target->data[tindex++];
> 			source->data[sindex+2] = target->data[tindex++];
...
> }
> /// <eof>

-- 
Ben.

[toc] | [prev] | [standalone]


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


csiph-web