C declarations are half backward
-
Does it bother anyone else that you declare a pointer like:
char* sz; // pointer type, pointer declared *with* type
But an array is declared like this:
char sz[1024];// array type, array declared *after* var name
I think it's inconsistent, and I think the array specifier should have been declared with the type since it's essentially a type modifier like * and & Maybe it's just me?
Real programmers use butterflies
When I was learning C, it bothered and confused me. Now, I recognized it as the type and it doesn't bother me. Is that age, tolerance, or just exposure to too many languages???
-
When I was learning C, it bothered and confused me. Now, I recognized it as the type and it doesn't bother me. Is that age, tolerance, or just exposure to too many languages???
Yeah I've coded in C and C++ for a long time, to the point where it doesn't confuse me. I just don't like the inconsistency. I understand why it is from a syntax perspective. In c#
int[] array = new int[10];
But in C it doesn't make sense to use new, and
int[10] array;
is ugly. Still, it just bugs me, because they're both type modifiers.Real programmers use butterflies
-
Without wishing to start a major language debate, I think its important to understand that C was designed to be efficient at using the underlying hardware of the machine, and the way things are declared reflects this: char *sz declares a single variable that points to a place in memory, supposedly holding a char value. This pointer (and here's where dragons lie!) can be made to point to anywhere and to anything regardless of its declaration, you are just telling the compiler that at the place where that pointer points, YOU consider there to be a char value (whether it is or not in reality). char sz[1024] says that at the address represented by sz is a reserved block of memory that holds (in theory) 1024 char items. In your code you can (with some severe caveats!) use both variables in the same way and it's up to you to remember and manage whatever you think you are looking at in that location - this is both the beauty and danger of a language like C - it allows you to manipulate things in much the same way as in assembler and with as few restrictions, but it provides no protection against you doing something stupid. However, even the early compilers would detect if you attempted to treat these two variables as exactly equivalent, but would often only warn rather than prevent it, allowing you to create absolute havoc. Much code rot is caused by the developer incorrectly assuming that, by default, either of these variables is initialised (which is why most compilers these days will attempt to put something sensible in newly declared variables to protect the innocent). Before initialisation char *sz may contain a random address and even attempting to look at it might cause a total system crash if it accidentally points into hardware protected memory. With char sz[1024] though you can be sure that doing char x = *sz is safe because sz already holds a valid address and points into memory allocated to your program, what you don't know is what value you will actually get back from that place before the array is initialised. Why have I bored you all with this stuff? Because so many developers these days seem to know absolutely nothing at all about how the hardware they are driving works - that's fine if you are writing in a high-level domain specific language where everything like that is hidden - no help at all if you are writing a device driver for some complex piece of hardware that is integrated into an operating system of some sort.
I think you may have misunderstood me
char[] sz = char[100];
would be more consistent even if it requires extra typing. I'm not complaining about the way accessed either, just how it's declared. I don't mind that either way sz can be accessed via pointer or array index. In this case you could dereference it with a * like you can otherwise. I'm not arguing you shouldn't be able to. It's not a huge deal for me either. I've coded in the C and C++ for years so I'm used to it. It's just a syntax wrinkle i don't like.
Real programmers use butterflies
-
Does it bother anyone else that you declare a pointer like:
char* sz; // pointer type, pointer declared *with* type
But an array is declared like this:
char sz[1024];// array type, array declared *after* var name
I think it's inconsistent, and I think the array specifier should have been declared with the type since it's essentially a type modifier like * and & Maybe it's just me?
Real programmers use butterflies
You are thinking about it the wrong way, I believe. There is an implicit Algebra: * = 1/& so, char *p, LITERALLY says (*p) is a char. therefore &(*p) => Address of that char! but knowing the algebra & and * cancel each other out (as do & and [) So, p is a pointer to a specific char. And the beauty of this, is that how you declare it usually implies how you are going to use it. A fixed array is declared as char a[10]; Which again, says (to me), I want an array of 10 characters, a POINTS to the first character, and a[1] == *(a+1). I always found this part of C very expressive and self-explanatory. Of course, I learned PDP/11 Macro-11 Assembly BEFORE I learned C. So most of this was mapping to register level access of R0 vs (R0) [Memory direct and indirect addressing]. Mov 65, R0 ; Stores the value in the register Mov 65, (R0) ; Stores 65 at the memory location of R0 Mov 65, (R0++) ; Stores 65 at the memory location and increments the memory location AFTER to the next ; Note its been 35 years, the syntax is illustrative of the features. If you know how the variable is declared, you should instantly understand the various ways you can dereference it.
-
You are thinking about it the wrong way, I believe. There is an implicit Algebra: * = 1/& so, char *p, LITERALLY says (*p) is a char. therefore &(*p) => Address of that char! but knowing the algebra & and * cancel each other out (as do & and [) So, p is a pointer to a specific char. And the beauty of this, is that how you declare it usually implies how you are going to use it. A fixed array is declared as char a[10]; Which again, says (to me), I want an array of 10 characters, a POINTS to the first character, and a[1] == *(a+1). I always found this part of C very expressive and self-explanatory. Of course, I learned PDP/11 Macro-11 Assembly BEFORE I learned C. So most of this was mapping to register level access of R0 vs (R0) [Memory direct and indirect addressing]. Mov 65, R0 ; Stores the value in the register Mov 65, (R0) ; Stores 65 at the memory location of R0 Mov 65, (R0++) ; Stores 65 at the memory location and increments the memory location AFTER to the next ; Note its been 35 years, the syntax is illustrative of the features. If you know how the variable is declared, you should instantly understand the various ways you can dereference it.
We seem to be talking about two different things. I'm simply talking about type modifiers and how they are applied to types. In C the pointer modifier comes after the type, and the array modifier comes after the variable or member declaration. It's just a slight syntactic (purely cosmetic) inconsistency that has irked me for the years that I've used C and C++.
Real programmers use butterflies
-
I think you may have misunderstood me
char[] sz = char[100];
would be more consistent even if it requires extra typing. I'm not complaining about the way accessed either, just how it's declared. I don't mind that either way sz can be accessed via pointer or array index. In this case you could dereference it with a * like you can otherwise. I'm not arguing you shouldn't be able to. It's not a huge deal for me either. I've coded in the C and C++ for years so I'm used to it. It's just a syntax wrinkle i don't like.
Real programmers use butterflies
Fair enough 8)
-
The usage is odd as well:
char* p = ...
*p = 'x';Vs
foo f;
foo *pf = &f;
f.x = '?';
pf->x = '!';Why invent two access operators "." and "->", when you could just use "*pf.x" and be more consistent? Or use "->" to dereference all pointers? I get the feeling bits of the C spec were thrown in just before the submission deadline ... :laugh:
"I have no idea what I did, but I'm taking full credit for it." - ThisOldTony "Common sense is so rare these days, it should be classified as a super power" - Random T-shirt AntiTwitter: @DalekDave is now a follower!
The short answer is: because the language evolved. The longer, and actually informative, answer is the accepted answer to this post: pointers - Why does the arrow (->) operator in C exist? - Stack Overflow[^]
-
We seem to be talking about two different things. I'm simply talking about type modifiers and how they are applied to types. In C the pointer modifier comes after the type, and the array modifier comes after the variable or member declaration. It's just a slight syntactic (purely cosmetic) inconsistency that has irked me for the years that I've used C and C++.
Real programmers use butterflies
Okay, I apologize. Now, consider this, how do I declare 3-5 arrays of different sizes? char a[2],b[5],c[6],d[7]; char [2]a, ... char[2] a; char[5] b; char... also, neat trick, 2[c] == c[2]; // because ANSI declared n[c] == *(c+n), and therefore c[n] == *(n+c) I think I would be confused if it was any other way than it is now. The cool thing is you could use the preprocessor to make it work like you want (and be threatened by every living programmer for HORRIBLE form, LOL). [I used to use the preprocessor... A Lot... LOL]
-
Okay, I apologize. Now, consider this, how do I declare 3-5 arrays of different sizes? char a[2],b[5],c[6],d[7]; char [2]a, ... char[2] a; char[5] b; char... also, neat trick, 2[c] == c[2]; // because ANSI declared n[c] == *(c+n), and therefore c[n] == *(n+c) I think I would be confused if it was any other way than it is now. The cool thing is you could use the preprocessor to make it work like you want (and be threatened by every living programmer for HORRIBLE form, LOL). [I used to use the preprocessor... A Lot... LOL]
wait, are you declaring char [2]a backward to illustrate a point? just to be clear literally I'd ask for is a single change from this:
char sz[100];
To this
char[] sz[100];
Even if it requires extra typing it would be more consistent. Everything else would be the same. And I'd never abuse the preprocessor that way with the exception of using it to help code complicated compile time computations and make writing them easier. Like the Spirit parsing framework.
Real programmers use butterflies
-
Quote:
Why do we do this? I'll tell you... I don't know. But because of this, every one of us knows what a pointer is, how to dereference it, and what K&R expect of him.
With apologies to Sholem Aleichem and to the producers of Fiddler on the Roof :)
Freedom is the freedom to say that two plus two make four. If that is granted, all else follows. -- 6079 Smith W.
Beautiful. I'm proud of you.
"The difference between genius and stupidity is that genius has its limits." - Albert Einstein
"If you are searching for perfection in others, then you seek disappointment. If you seek perfection in yourself, then you will find failure." - Balboos HaGadol Mar 2010
-
Without wishing to start a major language debate, I think its important to understand that C was designed to be efficient at using the underlying hardware of the machine, and the way things are declared reflects this: char *sz declares a single variable that points to a place in memory, supposedly holding a char value. This pointer (and here's where dragons lie!) can be made to point to anywhere and to anything regardless of its declaration, you are just telling the compiler that at the place where that pointer points, YOU consider there to be a char value (whether it is or not in reality). char sz[1024] says that at the address represented by sz is a reserved block of memory that holds (in theory) 1024 char items. In your code you can (with some severe caveats!) use both variables in the same way and it's up to you to remember and manage whatever you think you are looking at in that location - this is both the beauty and danger of a language like C - it allows you to manipulate things in much the same way as in assembler and with as few restrictions, but it provides no protection against you doing something stupid. However, even the early compilers would detect if you attempted to treat these two variables as exactly equivalent, but would often only warn rather than prevent it, allowing you to create absolute havoc. Much code rot is caused by the developer incorrectly assuming that, by default, either of these variables is initialised (which is why most compilers these days will attempt to put something sensible in newly declared variables to protect the innocent). Before initialisation char *sz may contain a random address and even attempting to look at it might cause a total system crash if it accidentally points into hardware protected memory. With char sz[1024] though you can be sure that doing char x = *sz is safe because sz already holds a valid address and points into memory allocated to your program, what you don't know is what value you will actually get back from that place before the array is initialised. Why have I bored you all with this stuff? Because so many developers these days seem to know absolutely nothing at all about how the hardware they are driving works - that's fine if you are writing in a high-level domain specific language where everything like that is hidden - no help at all if you are writing a device driver for some complex piece of hardware that is integrated into an operating system of some sort.
You, in your last paragraph, point out my pet peeve with C#; Everything is separated by '.' - it makes things easier and detaches the developer from what the object really is. Value in enum? Member in a class? Namespace? OK - they worked to make all of this (seem to) work together, smoothly, but it also, by shielding the users from reality, fosters and allows the maintenance of a degree of ignorance. Essentially, C# is a dumbed-down version of C++ . Hardly a surprise as the original stated intent of MicroSloth, when they created it, was to wean users away from vb.NET . Probably this type of pseudo-rant "points" to my stogie attitude developed with age. Or that I learned assembler before C . Quick Anecdote: when my brother got his first computer I worked on getting him to master DOS (a while ago!). At first he started but then he stopped: they installed Windows. I asked him how he'll fix anything if there's a problem, without understanding what Windows was running on. His answer? He'll ask me. And so it goes with C# vs C/C++ background developers.
"The difference between genius and stupidity is that genius has its limits." - Albert Einstein
"If you are searching for perfection in others, then you seek disappointment. If you seek perfection in yourself, then you will find failure." - Balboos HaGadol Mar 2010
-
Does it bother anyone else that you declare a pointer like:
char* sz; // pointer type, pointer declared *with* type
But an array is declared like this:
char sz[1024];// array type, array declared *after* var name
I think it's inconsistent, and I think the array specifier should have been declared with the type since it's essentially a type modifier like * and & Maybe it's just me?
Real programmers use butterflies
As I understand it declarations are written as if operators e.g. you would write "name[123]" to access the 123'rd element in the array named "name" so that's how it is declared. Maybe it should be "[123]name".
-
As I understand it declarations are written as if operators e.g. you would write "name[123]" to access the 123'rd element in the array named "name" so that's how it is declared. Maybe it should be "[123]name".
You seem to be talking about accessing the array, not declaring it. I'm talking about declaring it. Edit: Or if you are, then I think get your point? My response would be that pointers aren't declared like pointer operations.
Real programmers use butterflies
-
Does it bother anyone else that you declare a pointer like:
char* sz; // pointer type, pointer declared *with* type
But an array is declared like this:
char sz[1024];// array type, array declared *after* var name
I think it's inconsistent, and I think the array specifier should have been declared with the type since it's essentially a type modifier like * and & Maybe it's just me?
Real programmers use butterflies
honey the codewitch wrote:
I think it's inconsistent, and I think the array specifier should have been declared with the type since it's essentially a type modifier like * and &
One thing it's *not* is inconsistent - the pointer modifier belongs with the variable, *not* the type. For example, the following fragment declares a pointer to integer variable and an integer variable. ``` int *pa, a; ``` See [this Godbolt](https://godbolt.org/z/xhd8KP)... One option, were you using C++... ``` template using Array = T[N]; template using Ptr = T*; Array test_array; Ptr test_pointer; ```
Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p
-
As I understand it declarations are written as if operators e.g. you would write "name[123]" to access the 123'rd element in the array named "name" so that's how it is declared. Maybe it should be "[123]name".
You could use `123[name]` as an alternative - that matches the original PDP addressing mode syntax better as well, I suspect!
Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p
-
honey the codewitch wrote:
I think it's inconsistent, and I think the array specifier should have been declared with the type since it's essentially a type modifier like * and &
One thing it's *not* is inconsistent - the pointer modifier belongs with the variable, *not* the type. For example, the following fragment declares a pointer to integer variable and an integer variable. ``` int *pa, a; ``` See [this Godbolt](https://godbolt.org/z/xhd8KP)... One option, were you using C++... ``` template using Array = T[N]; template using Ptr = T*; Array test_array; Ptr test_pointer; ```
Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p
Stuart Dootson wrote:
One thing it's not is inconsistent - the pointer modifier belongs with the variable, not the type.
Yet it's a type modifier. A pointer to an int is a different type than an int.
Real programmers use butterflies
-
You seem to be talking about accessing the array, not declaring it. I'm talking about declaring it. Edit: Or if you are, then I think get your point? My response would be that pointers aren't declared like pointer operations.
Real programmers use butterflies
They aren't? I would declare a pointer using the rules of operator precedence always starting with the identifier e.g. "char* name" and utilize it as an operator as "*name" so except for the white space and the casting operator "char" which is no longer needed they are the same. Cheerios
-
They aren't? I would declare a pointer using the rules of operator precedence always starting with the identifier e.g. "char* name" and utilize it as an operator as "*name" so except for the white space and the casting operator "char" which is no longer needed they are the same. Cheerios
I think we're misunderstanding each other. My OP maybe wasn't as clear as it should have been. I've always declared pointers with the * next to the type. You CANNOT declare arrays that way. Hence my complaint.
Real programmers use butterflies
-
I think we're misunderstanding each other. My OP maybe wasn't as clear as it should have been. I've always declared pointers with the * next to the type. You CANNOT declare arrays that way. Hence my complaint.
Real programmers use butterflies
Greetings My point is that if you accept the rules of operator precedence and associativity which I am assuming you do than you must accept the rules of declaration since they are identical. Otherwise you must argue against both and insist e.g. that array elements be referenced as "[123]name" or pointer targets as "name*". Or perhaps you would argue that the rules of declaration be different from the rules of operation but that would complicate things. Kind Regards Cheerios
-
Greetings My point is that if you accept the rules of operator precedence and associativity which I am assuming you do than you must accept the rules of declaration since they are identical. Otherwise you must argue against both and insist e.g. that array elements be referenced as "[123]name" or pointer targets as "name*". Or perhaps you would argue that the rules of declaration be different from the rules of operation but that would complicate things. Kind Regards Cheerios
Oh, I get you. I guess using operator precedence on type modifiers kind of threw me, but i can see why you look at it that way. :)
Real programmers use butterflies