Wednesday, October 27, 2021

Digest for comp.lang.c++@googlegroups.com - 25 updates in 2 topics

Juha Nieminen <nospam@thanks.invalid>: Oct 27 04:43AM


> And you didn't bother to mention the diagnostic? I get
> warning: ISO C++ forbids converting a string constant to ???char*??? [-Wwrite-strings]
> And of course with "-pedantic-errors" it becomes a fatal error.
 
If gcc (or whichever compiler this is) doesn't give an outright error from
trying to assign a const pointer to a non-const one without an explicit
cast, then it's non-standard-conforming and I would classify it as a
defect in the compiler.
 
I think that the compiler should be fully standard-conforming by default,
and be more permissive and have non-standard extensions and behavior only
when explicitly specified using command-line parameters. Not the other
way around.
Juha Nieminen <nospam@thanks.invalid>: Oct 27 04:44AM

> Sorry, I have limited tolerance for smart asses so yes, I stopped reading.
 
Then why are you responding?
Juha Nieminen <nospam@thanks.invalid>: Oct 27 04:57AM


> [hopeless effort at self justification]
 
> You said arrays couldn't be declared as parameters. I showed you they could,
> end of. What the compiler does with it under the hood is irrelevant.
 
You seem to be confusing pointers with arrays. Which is not completely
unexpected given that this confusing is very common among less
experienced C (and C++) programmers, as the language makes that
distinction oftentimes hard to discern.
 
(I know that you will not read past this, but I'm going to try to
explain it anyway.)
 
An array and a pointer are not the same thing, not even in C. While an
array can often be confused with a pointer, because an array almost always
implicitly converts to a pointer-to-its-fist-element implicitly whenever
one is needed, they are not the same thing. The most prominent situation
where this distinction is made is when using the sizeof operator.
The sizeof of a pointer will be just the size of the pointer itself
(typically 4 or 8). The sizeof of an array will be the entire amount
of bytes that the array takes.
 
uint32_t values[10];
uint32_t *ptr = values;
 
sizeof(values); // will be 40.
sizeof(ptr); // will typically be 4 or 8.
 
In C, and C++, you cannot pass arrays by value to a function as-is.
You can only pass a pointer to an array. (This pointer will carry
no information about the number of elements in the array, even if
you use the confusing syntax where it looks like it does.)
 
The only way you can pass an array to a function by value (both
in C and C++) is by enclosing it inside a struct (or class) and
passing an object of that type by value:
 
struct MyArray
{
int values[10];
};
 
// Genuinely gets the entire array by value, not just a pointer:
void foo(struct MyArray theArray);
 
You can use the array syntax in a function parameter declaration, but
that's just confusing syntax sugar:
 
// It does not get an array of 10 elements by value, it's just
// getting a pointer. The "10" in the declaration is meaningless:
void foo(int values[10])
{
printf("%u\n", sizeof(values)); // will print 4 or 8, not 40
}
 
Honestly, I think it was a bad idea to add that syntactic sugar to C.
It only causes confusion for no benefit.
Juha Nieminen <nospam@thanks.invalid>: Oct 27 05:01AM

>>> Bus error: 10
 
>>For starters, that's in no way guaranteed to happen. Learn standard C.
 
> It is on *nix and thats good enough for me.
 
I would like a citation to the Single Unix Specification, or to POSIX,
that states so.
 
(I'm not saying it's not there. I just find it doubtful because not all
CPU architectures have support for that.)
 
>>Secondly, if you think that a runtime diagnostic is as good as a compile-time
>>diagnostic, then you have still a LOT to learn about software development.
 
> All I'm saying is the bug would exhibit itself pretty quickly.
 
Then you are very inexperienced in software development.
Juha Nieminen <nospam@thanks.invalid>: Oct 27 05:04AM


> Noooo! Really??
 
> Have you actually read anything I wrote or are you just jumping on the
> bandwagon of what others have said in order to try and sound clever?
 
Actually he has. He read your assertion that "[] means modifiable
and * means non-modifiable", and is proving you wrong: * can be
perfectly well modifiable.
 
Of course you will never acknowledge this. Instead you'll just start
dodging with insults.
David Brown <david.brown@hesbynett.no>: Oct 27 08:29AM +0200

On 27/10/2021 06:43, Juha Nieminen wrote:
> trying to assign a const pointer to a non-const one without an explicit
> cast, then it's non-standard-conforming and I would classify it as a
> defect in the compiler.
 
You may /prefer/ an error (stopping compilation) rather than a warning,
but the standard does not require it. A diagnostic message is all that
is needed on constraint errors.
 
I guess someone decided that a warning (always enabled, without
requiring any flags) is a good compromise for the convenience of people
converting old C code to C++.
 
(I personally would prefer a hard error on this and many other faults in
code, requiring particular options to allow people to compile
questionable code. But backwards compatibility applies to build systems
as well - there is a strong feeling that where possible, code that could
be compiled with particular flags before should continue to be compilable.)
 
It's the website rextester.com that is at fault in hiding warnings by
default. That is idiotic, IMHO.
 
> and be more permissive and have non-standard extensions and behavior only
> when explicitly specified using command-line parameters. Not the other
> way around.
 
In this respect, gcc /is/ fully conforming.
 
From C++14, 1.4p2 "Implementation compliance"
 
"""
If a program contains a violation of any diagnosable rule or an
occurrence of a construct described in this Standard as
"conditionally-supported" when the implementation does not support that
construct, a conforming implementation shall issue at least one
diagnostic message.
"""
RacingRabbit@watershipdown.co.uk: Oct 27 07:57AM

On Tue, 26 Oct 2021 12:23:37 -0400
 
>No, I said "it's not permitted to declare functions that take arrays as
>arguments, but it is permitted to declare a function parameter as if it
>were an array."
 
There is no difference. As I said, what the compiler does with it under the
hood is not the point. The syntax declares an array.
 
>When I run that program, it says "pointer". What do you get when you run it?
 
Same. Not the point, its declared as an array.
Juha Nieminen <nospam@thanks.invalid>: Oct 27 08:47AM

>>were an array."
 
> There is no difference. As I said, what the compiler does with it under the
> hood is not the point. The syntax declares an array.
 
No, it doesn't. It declares a pointer. What do you think this will print?
 
#include <stdio.h>
 
void foo(int array[10])
{
printf("foo: sizeof(array) = %lu\n", sizeof(array));
}
 
int main()
{
int array[10];
int *ptr = array;
printf("main: sizeof(array) = %lu\n", sizeof(array));
printf("main: sizeof(ptr) = %lu\n", sizeof(ptr));
foo(array);
}
David Brown <david.brown@hesbynett.no>: Oct 27 11:07AM +0200

> hood is not the point. The syntax declares an array.
 
>> When I run that program, it says "pointer". What do you get when you run it?
 
> Same. Not the point, its declared as an array.
 
Do you have trouble understanding the difference between an array, and a
pointer to the first element of the array?
 
C arrays are /never/ passed to functions as parameters, nor are they
used directly in most expressions. (You can pass a struct that contains
an array as a field, but that's a struct, not an array.) It is a major
inconsistency in the type system of C, but one that works well in practice.
 
Do you know the difference between :
 
int ar1[10];
 
and
 
std::array<int, 10> ar2;
 
and how these may be passed to functions?
JohnnyCameLater@whatsthetime.net: Oct 27 02:29PM

On Wed, 27 Oct 2021 08:47:42 -0000 (UTC)
 
>> There is no difference. As I said, what the compiler does with it under the
>> hood is not the point. The syntax declares an array.
 
>No, it doesn't. It declares a pointer. What do you think this will print?
 
Which parts of "syntax" and "under the hood" is confusing you. Perhaps in your
own language?
 
"syntaksi"
"konepellin alla"
 
Any clearer?
JohnnyCameLater@whatsthetime.net: Oct 27 02:30PM

On Wed, 27 Oct 2021 11:07:03 +0200
 
>> Same. Not the point, its declared as an array.
 
>Do you have trouble understanding the difference between an array, and a
>pointer to the first element of the array?
 
Do you have trouble understanding plain English? The syntax declares an array,
the fact the compiler converts that into a pointer isn't the point. Pun
intended.
David Brown <david.brown@hesbynett.no>: Oct 27 05:30PM +0200


> Do you have trouble understanding plain English? The syntax declares an array,
> the fact the compiler converts that into a pointer isn't the point. Pun
> intended.
 
I don't know whether you are trolling, or if you are simply so arrogant
that you would rather stay ignorant and insult people than admit to
making a mistake and appreciate the help and advice you are given.
Either way, feel free to come back with questions once you have grown up
a little, and feel free to stay away until that day.
James Kuyper <jameskuyper@alumni.caltech.edu>: Oct 27 11:38AM -0400

>> were an array."
 
> There is no difference. As I said, what the compiler does with it under the
> hood is not the point. The syntax declares an array.
 
The syntax uses [] rather than *. The semantics are those of a pointer,
not an array.
 
The semantics are NOT "under the hood" - they restrict what you can do
with the function without violating a constraint. They determine what
result you get when you apply the sizeof() or unary & operators to the
parameter. Most importantly, they determine what happens if you write
expressions such as "parameter[1] = 5".
 
Getting back to my original statement, declaring a parameter with
pointer semantics using the [] syntax does not allow you to pass an
array as the corresponding argument in the function call. All you can
pass is a pointer to the first element of the array - which is what any
lvalue of array type will be converted into if passed as an argument to
such a function.
 
Since C uses "pass by value" exclusively, if you were able to pass an
array as an argument, then the corresponding parameter would be a
separate array object with a different address, initialized by copying
from the array argument. Evaluation the expression "parameter[1] = 5"
would only affect the parameter, it would have no effect on the array
argument.
You can get some idea of how C would behave if such declarations were
possible, by declaring a struct type containing an array. Such a struct
could be passed into or returned by a function by value. It's
syntactically different from, but semantically equivalent to, passing
around the array itself by value.
 
The actual C semantics of such a function call are that the
corresponding parameter is a separate pointer object filled in by
copying the value of the pointer that the lvalue was converted to.
Evaluating the expression "parameter[1] = 5" would set the second
element of the array to 5.
James Kuyper <jameskuyper@alumni.caltech.edu>: Oct 27 11:39AM -0400

> On Wed, 27 Oct 2021 11:07:03 +0200
> David Brown <david.brown@hesbynett.no> wrote:
...
 
> Do you have trouble understanding plain English? The syntax declares an array,
> the fact the compiler converts that into a pointer isn't the point. Pun
> intended.
 
"array" vs. "pointer is a matter of semantics. [] vs * is a matter of
syntax. All you can say about the syntax is that it contains []. In most
contexts, [] in the syntax of a declaration corresponds to array
semantics. However, the standard is quite explicit about the fact that,
in this context, what [] means is pointer semantics.
 
This is not just quibbling. It determine which arguments can be passed
to the function without violating a constraint. Two function prototypes
are compatible only if the type that one of them declares for a given
parameter is compatible with the type declared by the other for that
same parameter. If one function prototype uses "int array[]" for one
parameter, and the other uses "* int pointer" for the same parameter,
those two prototypes are compatible.
JohnnyCameLater@whatsthetime.net: Oct 27 03:46PM

On Wed, 27 Oct 2021 17:30:43 +0200
>> the fact the compiler converts that into a pointer isn't the point. Pun
>> intended.
 
>I don't know whether you are trolling, or if you are simply so arrogant
 
Pot -> kettle.
 
>making a mistake and appreciate the help and advice you are given.
>Either way, feel free to come back with questions once you have grown up
>a little, and feel free to stay away until that day.
 
Go fuck yourself you patronising jerk.
JohnnyCameLater@whatsthetime.net: Oct 27 03:49PM

On Wed, 27 Oct 2021 11:38:54 -0400
>> hood is not the point. The syntax declares an array.
 
>The syntax uses [] rather than *. The semantics are those of a pointer,
>not an array.
 
The syntax defines an array. Why do you think you get compiler warnings if
you go OOB with an index value? Try it.
 
>The semantics are NOT "under the hood" - they restrict what you can do
 
Yes, they are.
 
tl;dr
JohnnyCameLater@whatsthetime.net: Oct 27 03:51PM

On Wed, 27 Oct 2021 11:39:16 -0400
>contexts, [] in the syntax of a declaration corresponds to array
>semantics. However, the standard is quite explicit about the fact that,
>in this context, what [] means is pointer semantics.
 
Oh really?
 
fenris$ cat t.c
#include <stdio.h>
 
void func(int a[2][3])
{
a[10][50] = 123;
}
 
 
int main()
{
int a[2][3];
func(a);
return 0;
}
fenris$ cc t.c
t.c:5:2: warning: array index 50 is past the end of the array (which contains 3
elements) [-Warray-bounds]
a[10][50] = 123;
^ ~~
t.c:3:11: note: array 'a' declared here
void func(int a[2][3])
^
1 warning generated.
 
Nuff said.
scott@slp53.sl.home (Scott Lurndal): Oct 27 04:13PM

>On 27/10/2021 16:30, JohnnyCameLater@whatsthetime.net wrote:
 
>>> On 27/10/2021 09:57, RacingRabbit@watershipdown.co.uk wrote:
 
>I don't know whether you are trolling,
 
Given the choice of nyms,and the name changes, my assumption has
been trolling. Best to simply ignore such posts.
Ben Bacarisse <ben.usenet@bsb.me.uk>: Oct 27 05:21PM +0100

>>semantics. However, the standard is quite explicit about the fact that,
>>in this context, what [] means is pointer semantics.
 
> Oh really?
 
Yes.
 
> ^
> 1 warning generated.
 
> Nuff said.
 
Not really. Note that the compiler does not complain about the first
index (10) being out of bounds. That's because (despite the badly
worded note) it's only the three-element objects pointed to by 'a' that
are in fact arrays with a known bound. Some compilers explain the issue
more clearly.
 
Here's gcc 11.2 giving much better, but identical, notes about these two
functions:
 
void func(int a[2][3])
{
a[10][50] = 123;
}
 
void func2(int (*a)[3])
{
a[10][50] = 123;
}
 
x.c: In function 'func':
x.c:3:11: warning: array subscript 50 is above array bounds of 'int[3]' [-Warray-bounds]
3 | a[10][50] = 123;
| ~~~~~^~~~
x.c:1:15: note: while referencing 'a'
1 | void func(int a[2][3])
| ~~~~^~~~~~~
x.c: In function 'func2':
x.c:3:11: warning: array subscript 50 is above array bounds of 'int[3]' [-Warray-bounds]
3 | a[10][50] = 123;
| ~~~~~^~~~
x.c:6:18: note: while referencing 'a'
6 | void func2(int (*a)[3])
| ~~~~~~^~~~~
 
--
Ben.
James Kuyper <jameskuyper@alumni.caltech.edu>: Oct 27 12:26PM -0400

> On Wed, 27 Oct 2021 11:39:16 -0400
> James Kuyper <jameskuyper@alumni.caltech.edu> wrote:
...
>> semantics. However, the standard is quite explicit about the fact that,
>> in this context, what [] means is pointer semantics.
 
> Oh really?
 
Yes, really.
 
> void func(int a[2][3])
> ^
> 1 warning generated.
 
The standard imposes no requirements on diagnostics - in particular, it
does not require them to correctly describe the problem - many
implementations occasionally generate incorrectly worded diagnostics,
even when describing legitimate errors, and this warning is one example.
The actual type of a is int(*)[3], not int[2][3], a fact that you can
confirm using sizeof(a) or &a (the difference between those types
disappears in all other contexts, due to the implicit array=>pointer
conversion).
 
This message is posted to C++. While C++ has many differences from C,
this isn't one of them, and in C++ a more convenient way to check the
type of a is to use typeid(a).name(). Unfortunately, the resulting
string is implementation-defined - on my machine it is a coded version
of the type, rather than a proper C++ type specification. However, if
you declare
 
int b(*)[3];
int c[2][3];
 
then you should find that typeid(a)==typeid(b), and typeid(a) !=
typeid(c). typeid(a).name() should be the same as typeid(b).name(), and
both should be different from the typeid(c).name(). Let me know what you
find when you try that.
 
There is an array bounds violation in your code, but it's not in a
itself, which is not an array. a is a pointer that can be used to point
at any unqualified array with an element type of int[3], regardless of
how large. However, whatever array you point a at, if a[10] refers to an
actual element of that array, then a[10][50] violates the bounds of the
3-element array that a[10] points at, not the bounds of a itself, which
has none.
 
You'll get the same error if you change a[10][50] to a[1][50], and there
wouldn't be any problem in func() itself if you changed it to a[10][2].
 
If you pass a pointer to func() which will still point at a different
element of the same array after 10 is added to it, then a[10][2] inside
of func() would also have defined behavior - which would be to change
the corresponding element of the pointed-at array, rather than the
corresponding element of a, which has none.
James Kuyper <jameskuyper@alumni.caltech.edu>: Oct 27 12:36PM -0400

> On Wed, 27 Oct 2021 11:38:54 -0400
> James Kuyper <jameskuyper@alumni.caltech.edu> wrote:
>> On 10/27/21 3:57 AM, RacingRabbit@watershipdown.co.uk wrote:
...
>> not an array.
 
> The syntax defines an array. Why do you think you get compiler warnings if
> you go OOB with an index value? Try it.
 
I did try it, and I don't get a compiler warning if I violate the
supposed leading dimension of that array, which is the dimension that
gets "adjusted" into a pointer:
 
 
static void func (int a[2][3])
{
a[4][2] = 123;
}
 
int main(void)
{
int b[8][3] = 0;
func(b);
return b[4][2];
}
 
Subscripting with a[i][j] with j>2 would be just as much of an array
violation if the type of a is int(*)[3] as it would be if the type of a
were int[2][3].
Chris Vine <chris@cvine--nospam--.freeserve.co.uk>: Oct 27 05:41PM +0100

On Wed, 27 Oct 2021 11:07:03 +0200
> used directly in most expressions. (You can pass a struct that contains
> an array as a field, but that's a struct, not an array.) It is a major
> inconsistency in the type system of C, but one that works well in practice.
 
I know what you mean - they are never passed by value as parameters -
but they can be passed by reference as an array rather than as a pointer
to their first element. In C++ you have this available: there is no
pointer decay and it will print 10:
 
void func (char (&arr)[10]) {
std::cout << sizeof(arr) << std::endl;
}
 
int main() {
char arr9[9];
char arr10[10];
// func(arr9); // won't compile
func(arr10); // OK
}
 
In C and C++ you have this, which will also print 10:
 
void func (char (*arr)[10]) {
std::cout << sizeof(*arr) << std::endl;
}
 
int main() {
char arr9[9];
char arr10[10];
// func(&arr9); // won't compile
func(&arr10); // OK
}
 
None of this detracts from the fact that your nym-shifting correspondent
is not only clueless but also unable to learn.
 
David Brown <david.brown@hesbynett.no>: Oct 27 07:02PM +0200

On 27/10/2021 18:41, Chris Vine wrote:
> but they can be passed by reference as an array rather than as a pointer
> to their first element. In C++ you have this available: there is no
> pointer decay and it will print 10:
 
You can do that in C++, not in C. References in C++ are basically the
same concept as const pointers (as distinct from pointers to const),
just with a slightly different syntax. Your "func" here is not taking
an array as a value parameter (like C, you can't do that in C++ with
plain arrays), nor is it using array syntax as a means of specifying a
pointer to the first element. It is a pointer to an /array/.
 
 
> void func (char (*arr)[10]) {
> std::cout << sizeof(*arr) << std::endl;
> }
 
Yes, that is much the same as a reference in C++ (though you'd be
slightly closer with "char (*arr)[10]" ).
 
 
(I think that references are often better than pointers - they can be
safer and clearer. But they are not fundamentally different, as can be
seen by looking at implementations - they are convenient syntactic sugar.)
 
 
> None of this detracts from the fact that your nym-shifting correspondent
> is not only clueless but also unable to learn.
 
Indeed.
"Heitber Andrés Montilla Ramirez" <montillaramirezh@gmail.com>: Oct 26 06:24PM -0700

Hi everyone I want to know why this error apperars to my code, I'm trying to do an OpenGL App Using codeblocks, I re-checked the code twice with the original tutorial and everything is ok.
now the compiler throws the following error:
 
|error: invalid conversion from 'const void*' to 'HANDLE {aka void*}' [-fpermissive]|
 
I want your help to solve this issue.
 
 
 
#define GLUT_DISABLE_ATEXIT_HACK
#define GLEW_STATIC
 
#if defined(_WIN32) || defined(_WIN64)
#include <windows.h>

No comments: