|
Member 10753505 wrote: arrays
int x[2];
0[x] = 1[x]; is perfectly valid and utterly disgusting in C/C++.
Software Zen: delete this;
|
|
|
|
|
Meh. They are technically a data type but they need to lean on someone else to have meaning in their lives. They're like the really needy data type the other data types only play with because he has cool toys.
cheers
Chris Maunder
|
|
|
|
|
Not always : a void pointer lives its own live and you can made point it on every type or on... nothing !
|
|
|
|
|
void pointers make me sad.
cheers
Chris Maunder
|
|
|
|
|
Chris Maunder wrote: void pointers make me sad.
cheers
Chris Maunder
So appearently, you haven't seen any void pointers lately
|
|
|
|
|
I've always liked option 3: char * c . It avoids the problems char* c, d; can cause but still keeps it separate from the name. * is just like const or any other modifier. You wouldn't write constchar* c so why mash them together just because it's a single character (and allowed)?
|
|
|
|
|
When doing more than one variable declaration makes sense to put the * correctly, or you do not get what you expect.
When writing:
char* a,b,c;
you get the equivalent of:
char *a,b,c;
and you would probably expect:
char *a,*b,*c;
|
|
|
|
|
Because that's how the compiler parses it. The * binds to the variable not the type.
Think about
char* a, b;
This suggests that b is also a char *, but actually it is only a char. Much clearer when you write
char *a, b;
(Not that I would advocate doing either - even better to have two separate declarations - but it illustrates the point).
Ian Brockbank
"Legacy systems are systems that are not protected with a suite of tests. ... You are building legacy code every time you build software without associated tests." - Mary and Tom Poppendieck, Implementing Lean Software Development.
|
|
|
|
|
If you always puts your declarations on separate lines (or separated by ';') it doesn't matter. But if you do -- be aware.
Say that you have;
char* c;
char* d;
char* e;
and, for some reason, probably even a good one, decides to put them on one line ... in a bit of hurry so that you ends up with;
char* c,d,e;
But if you had
char *c;
char *d;
char *e;
there is a pretty good chance you would end up with;
char *c, *d, *e;
This is also the reason for the typedef's of pointers, eg.
typedef char * char_p;
char_p c;
char_p d;
char_p e;
would be
char_p c, d, e;
rgds /Jonas
ps.
char* c, d, e; --> char* c; char d; char e;
|
|
|
|
|
|
Why 68? Well, it was a fun language, especially for its time. But the language did't define a concrete syntax at all (there was an Algol68 with keywords in German - fully conformant to the Algol68 standard), so you couldn't use it to settle any concrete syntax arguments.
Switching to C# is really a far better solution: Make everything pointers, so that you never say that it is a pointer. If it is an object, then a name of that object is a pointer to it. No way to avoid. That makes it so much simpler, never having to worry about this being a struct, that being a pointer to a struct and something else being a pointer to a pointer to an array of pointers to a struct...
|
|
|
|
|
Thank you for your reply. I was a programmer years ago, and don't know C# too well. I'd be interested to know how, in C#, you would do this ...
REF INT ri;
INT i1, i2;
BOOL condition;
...
( condition | ri := i1 | ri := i2 );
ri := 1;
...
It's probably blindingly obvious, but, as I say, I'm not conversant with C#
|
|
|
|
|
Simple
Its C that is the pointer not the char.
So char *c makes more sense
Or read it in reverse (a standard way to understand C/C++)
C is a pointer to char
It also looks nicer!
|
|
|
|
|
As an aside, in the last century the leading PC C++ compiler vendor was not Microsoft but Borland. One day they got too big for their boots and issued a proclamation which dictated that all users of their IDE must code in their prescribed style - which included suffixing the "*" to the type instead of K&R's prefixing "*" to the variable name. It was at this point that I stopped using Borland.
For the sake of consistency, I can't resist also applying the K&R style to references too; although I'm clearly flying in the face of convention from the majority of code examples that I see in books and on-line.
|
|
|
|
|
I still prefer Borland C/C++ when I write C; I don't recall being forced one way or the other, but I'll try it later.
None of the following compilers complained about char* a , b :
HP C V7.3-009 on OpenVMS Alpha V8.3
Borland C++ 5.5 for Win32 Copyright (c) 1993, 2000 Borland
gcc version 3.2 (mingw special 20020817-1)
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
I expected HP C to complain because I compiled with CHECK messages enabled:
CHECK Messages reporting code or practices that,
although correct and perhaps portable, are
sometimes considered ill-advised because
they can be confusing or fragile to
maintain. For example, assignment as the
test expression in an "if" statement.
modified 31-May-18 12:40pm.
|
|
|
|
|
As others have pointed out before, the issue is
char* c, d;
vs.
char *c, *d;
The C++ grammar says that a declaration has the form
decl-specifier-seq init-declarator-list;
char is the decl-specifier, and what follows is one or more declarators (with optional initializers). *c is a declarator, and *d (or plain d) is another one.
So, if you write char* c then you're needlessly confusing your (and your reader's) mental image of the C++ grammar.
|
|
|
|
|
Actually, the reason is that 'char*' is not a type. A '*' belongs to the variable. In other words, this is valid C code:
char *pch, ch;
ch = 'A';
pch = &ch;
I'm a pure C programmer. I don't know how it works for C++ though.
|
|
|
|
|
The K&R answer is probably good enough. But I also taught it as the algebraic expression, that
* = 1/& (or * is the inversion of &).
Therefore declaring "char *c" says "*c" is a character, and &(*c) => Pointer, but & and * cancel.
Therefore c is a pointer to a character.
So, if you view it as *c is a the char in question, I think it explains that approach pretty clearly.
Having learned C a VERY long time ago, I have always used, and mostly saw "char *c" or "char c[]"!
the scary part in the old days was explaining how:
13[c] = 'x';
would be handled, as it DID compile!
and according to the answer definition of [] at the time, it was converted to:
*(13+c) = 'x';
and therefore was the same as c[13] = 'x';
|
|
|
|
|
char *c better aligns with C/C++ philosophy, but char* c is safer.
The syntax char *c says *c (c dereferenced) is a char , which makes c a pointer to char . However, teaching/learning this syntax/philosophy can be hard when people are just getting introduced to pointers.
Also, the declaration char *c, d makes c a char* , but d a char . This confuses beginners who are used to declarations such as int a, b which makes both a and b int s.
Thus, the declaration char* c is preferred: easier to learn and safer.
|
|
|
|
|
nullusDefectus wrote: Also, the declaration char *c, d makes c a char* , but d a char . This confuses beginners who are used to declarations such as int a, b which makes both a and b int s.
Thus, the declaration char* c is preferred: easier to learn and safer.
Your claim and conclusion are backwards! It's writing char* c, d; that confuses beginners for the exact reason that you give.
Writing char *c, d; is the correct way to teach, learn, and remind yourself and readers of your code that the * applies to c only.
Given the language grammar...
simple-declaration ::= decl-specifier-seq init-declarator-list(optional) ;
Note the space ---^
... writing...
char *c;
---^
... also demonstrates that you know what you're doing. This is how you explain it to beginners and they will remember...
|
|
|
|
|
I always the * next to the variable since you can convert most types into a pointer with the * modifier. Otherwise, this looks inconsistent:
char *p0;
char *p1, *p2;
Uwe Baemayr
Senior Software Developer
Micro Focus
|
|
|
|
|
char *c; matches the structure of the C grammar. If you declare three pointers, the declaration looks like char *c, *d, *e;
But people think of the '*' as belonging with the type, so they write char* c;
|
|
|
|
|
modified 29-May-18 12:20pm.
|
|
|
|
|
There are indeed pointer types, but there are no pointer type specifiers. The pointer-ness of something is specified by a combination of the type specifier(s) and the declarator. For a pointer like
char *p;
the type of p is "pointer to char " or char * , but that type is obtained by the combination of the type specifier char and the pointer declarator *p . Sure, you can write it as char* p; , but it will be parsed as char (*p); .
Something like
T *p1, *p2, *p3; should be perfectly understandable to anyone who understands C and C++ declaration syntax, but nobody does because it's not taught properly for some bizarre reason. It's such a fundamental part of the language, but it's invariably glossed over in every introductory text so as not to scare off beginners. So people inevitably bluescreen the first time they see something like a pointer to an array or a pointer to a function because the simplistic-to-the-point-of-being-wrong version of C declaration syntax they were taught doesn't account for it.
Yes, pointers are scary and difficult to understand at first. They're also a fundamental part of C programming (less so C++, but still important). C (and C++) declaration syntax needs to be taught properly and completely. But since it isn't, we need to come up with a bunch of coding standards to make up for it. So, no more than one declaration per line, because it's too hard to explain how char* a, b; really works.
Once you understand the rules, pointer declarations (including pointers to arrays, pointers to functions, pointers to arrays of functions returning pointers to arrays of pointers to int) make perfect sense. But apparently nobody understands the rules, so the language looks arbitrary and capricious.
|
|
|
|
|
I've noticed you italicized a lot of things relating to "understanding" how the language works. Many who do understand it feel the declaration syntax sucks inherited from C is a PITA.
If only programmers were taught declaration syntax, they'd come across this and the intention would be clear:
int (*f(int x))[3]
{
}
Also, I think my argument is somewhat supported by:
using T = char*;
T a, b;
Yes, I understand the grammar, and yes, I understand how this is different vis-a-vis grammar, but I'm not arguing about the grammar, I'm arguing about what _style_ is more "C++-esque". Here, T is the type specifier with no pointer declarator. The _type_ is actually now `char*` So when declaring these two names, they have the same types. That's the more natural use case one would expect from a programming language. Clearly, this is a matter of taste, but again, I'll point out that Bjarne Stroustrup is clearly on my side of this disagreement. Here's a funny quote from one of the links I included in my first post:
"The flip side of this is that you have to deal with old mistakes and with compatibility problems. For example, I consider the C declarator syntax an experiment that failed"
From this interview: Slashdot | Interviews | C++ Answers From Bjarne Stroustrup
|
|
|
|
|