Valhalla Legends Forums Archive | C/C++ Programming | Pointer Syntax Opinions

AuthorMessageTime
FrOzeN
[code]int main(int argc, HERE) {
    return 0;
}[/code]

Where it says "HERE", the Array of Array of Characters goes. Which would be the most practical way of writing it?

[list]
[li]char* argv[][/li]
[li]char *argv[][/li]
[li]char** argv[/li]
[li]char **argv[/li]
[li]Others..?[/li]
[/list]

I just started doing C/C++ programming again, and I'm trying to pick up on the most conventional methods of coding.

[EDIT] Also, in a program that doesn't use the Command Line arguments. Should you still put the variables in the main parentheses? // If there not used (but coded in), do they even get compiled in as part of the .exe? [I'm using gcc on Dev-Cpp]
April 1, 2006, 4:10 AM
rabbit
char* and char** should give errors...

Anyway, I usually write it as char **argv, though it's entirely personal preference.  How you write it doesn't matter all that much.

Also, you can do char argv[][]
April 1, 2006, 3:05 PM
Kp
[quote author=rabbit link=topic=14644.msg149553#msg149553 date=1143903945]
char* and char** should give errors...

Anyway, I usually write it as char **argv, though it's entirely personal preference.  How you write it doesn't matter all that much.

Also, you can do char argv[][]
[/quote]

Why is char** illegal, but char ** OK?

Frozen: arguments are never compiled into the executable, since then it'd be a real mess to change them.  Omitting the declaration ensures the compiler doesn't warn you about them being unused, but should have no effect on the code (versus declaring them and then never referencing them).  In both cases, an optimized binary should ignore the arguments entirely.
April 1, 2006, 4:03 PM
K
[quote author=rabbit link=topic=14644.msg149553#msg149553 date=1143903945]
char** should give errors...I usually write it as char **argv.
[/quote]

The spacing of pointer and reference characters don't matter at all.
char** foo, char **foo, char ** foo, char* *foo, etc, all have the same meaning.

Many people prefer to put the pointer or reference indicator next to the variable rather than the type for this reason:

[code]
// a is a char*; b is a char.
char* a, b; // the placement by the type seems to indicate that both should be char pointers.
char *a, b; // this placement clarifies that only a is a pointer.
[/code]

[code]
[/code]
April 1, 2006, 8:23 PM
rabbit
Ok then.  Something is learned every day.
April 1, 2006, 9:22 PM
FrOzeN
[quote author=Kp link=topic=14644.msg149554#msg149554 date=1143907380]
Frozen: arguments are never compiled into the executable, since then it'd be a real mess to change them.  Omitting the declaration ensures the compiler doesn't warn you about them being unused, but should have no effect on the code (versus declaring them and then never referencing them).  In both cases, an optimized binary should ignore the arguments entirely.
[/quote]
Ah, I see now. I originally started in VB6 having no understanding on how programs work, then now moving into C++ GUI's I picked up the structure and how event procedures are created etc.. my next step soon is to look into the raw .exe and see how there put together.

Also, I think char *argv[] will be easiest for me to understand for now. That way it clearly shows it's an array, aswell as showing that argv is the pointer and not any others which may be declared on the line. :)
April 3, 2006, 7:42 AM
rabbit
You should remember that an unsized array is a pointer: they are interchangable.
April 3, 2006, 2:10 PM
Myndfyr
[quote author=FrOzeN link=topic=14644.msg149667#msg149667 date=1144050161]
Also, I think char *argv[] will be easiest for me to understand for now. That way it clearly shows it's an array, aswell as showing that argv is the pointer and not any others which may be declared on the line. :)
[/quote]
Generally, at least I prefer this way (and I would think it tends to be what is thought of as best), to attach the pointer declaration to the type, for several reasons, not the least of which is what K said:
[quote author=K link=topic=14644.msg149558#msg149558 date=1143922990]
Many people prefer to put the pointer or reference indicator next to the variable rather than the type for this reason:

[code]
char *a, b; // this placement clarifies that only a is a pointer.
[/code]
[/quote]
C's grammar rules don't specify whether b should be a pointer or not in that case.  If you attach the * to the type name (for char*), there is no doubt that both a and b are char*, and not that a is char* and b is just char.

The other reason I tend to prefer that is because when you use the * modifier you're modifying the type of the variable, not the variable itself.  If you have char *argv[], you're not sure if you're working with a pointer of char arrays, an array of char pointers, or something else.  Although technically speaking it doesn't matter, when you get into more strongly-typed languages it does.  If you're working with a char pointer, or an array of char pointers, use char* identifier[]. 

You also don't need a variable identifier to group the pointer operator with the type.

[quote author=FrOzeN link=topic=14644.msg149667#msg149667 date=1144050161]
That way it clearly shows it's an array, aswell as showing that argv is the pointer
[/quote]
See though, you're not understanding correctly.  argv is not a pointer, it's an array OF pointers.  Sure, an array is a pointer in and of itself, and you could say:
[code]
int main(int argc, char** argv);
[/code]
...which indicates the double indirection you're going through with the array anyway; it just happens that thinking of the type as an array of char* (which is synonymous with strings in C) is a bit easier than thinking of the variable as a pointer to string pointers.

As an example, compile the following program:
[code]
#include <iostream>

int main(int, char**);

using namespace std;

int main(int argc, char** argv)
{
    int i;
    for ( i = 0; i < argc; i++ )
    {
        cout << *(argv + i) << endl;
    }
}
[/code]
Run it from a command line and include some arguments after it.  The output would be the same as this program:
[code]
#include <iostream>

int main(int, char**);

using namespace std;

int main(int argc, char* argv[])
{
    int i;
    for ( i = 0; i < argc; i++ )
    {
        cout << argv[i] << endl;
    }
}
[/code]

Please note that this sample was not tested ahead of time.  I'm banking on the memory that cout << char* prints a null-terminated string.  ;)
April 3, 2006, 4:36 PM
kamakazie
[quote author=MyndFyre[vL] link=topic=14644.msg149682#msg149682 date=1144082191]
[quote author=K link=topic=14644.msg149558#msg149558 date=1143922990]
Many people prefer to put the pointer or reference indicator next to the variable rather than the type for this reason:

[code]
char *a, b; // this placement clarifies that only a is a pointer.
[/code]
[/quote]

C's grammar rules don't specify whether b should be a pointer or not in that case.  If you attach the * to the type name (for char*), there is no doubt that both a and b are char*, and not that a is char* and b is just char.
[/quote]

Yes it does. A quick glance at K&R says [tt]a[/tt] is a pointer and [tt]b[/tt] is not. There is no ambiguity.
April 3, 2006, 6:49 PM
Myndfyr
[quote author=dxoigmn link=topic=14644.msg149687#msg149687 date=1144090163]
Yes it does. A quick glance at K&R says [tt]a[/tt] is a pointer and [tt]b[/tt] is not. There is no ambiguity.
[/quote]

Hrm, I could swear I read that somewhere.  Maybe it's in that UNIX Haters e-book that FreeBSD guy gave me.  *shrug*

In any case, it doesn't change the fact that this syntax allows for bizarre and otherworldly meanings.  For clear code, stick the pointer decorations on the type.
April 3, 2006, 7:40 PM
Adron
On the topic of placement of whitespace, check out iocc for code like this:

[code]
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#define t(x) typedef x
#define G return
#define Y(x) x;x
#define e(s) exit(s);
#define b(x,o) x o x
#define Z while
#define y fclose
#define end static

t(signed)char U;t(struct) b(O,);

t(     U*)
H;     t(O
*)     *o;
struct O{ O* l, **h; void* L; } ; t(int)i; i P(U g) { G
isspace(g); } H D(H s){H p,r;if(!s)G 0;for(p=(H)s;*p &&
!P(*p); p++); if(r=malloc(p-s))for(p=r; *s&&! P(*s);p++
,s++)b(*,p=) s; G r;} void l(o p,O*x){*(o)x=* p; *p=x;}
#define m(x) do{ if(!(q = malloc(sizeof(O)))) e(1)q->l\
=0     ;q\
->     L=\
    x ; } while (0)
i(*R)(i) =putchar;i h(
    o f,H d,U c){O*q; f+=c;Z(d&&*d)
  { m(D(d)); l(f++, q); Z(*d && !P(*d
)) d++; Z(*d && P(*d)) d++; } G b(,0);}
    void k() { static U b(c,;) ?R(c):(c='\n'); }
    i main (i Q,     H *l){static o
  X;i t,j;   switch (Q
){ case       1: { H
*p, I [] ={
"aH"   " "
"B"     "0"
" "     "B"
""     "B"
""     " "
"B"     ","
" "   ","
" `"   "0 "
"b0 " "@, "
  "0 Hb,"       " B2 "
  "H0 b, B b" "H HB b`, "
    "H, @ 2 `, "     "@2 H2 BH Bb"
      " b@","AH B0 BB B, , `0 b0 @, 0 Hb, B2 H0"
" b, B bH HB b`, H, @ 2 `, @2 H2 BH Bb"
  " b@","0bHb, HbH `H2 @b, @H @0 B@ "
      "b@ bH0 bHB",".HHH","?`H0",
",b@b,"," +", 0}; p=I;

    if (!(X=calloc(
6<<6,sizeof(O*))))e(1)
    do{h(X,(*p)+1,**p);} Z(*(++p));
  D: if ((t = getchar()) >= 0) { k();
goto u;}e(0)}case 2:{U *p,e[33]; b(i, )
    ,w;for(i=0;i<34;i++)i[e]=b(0,;w=);p=e; Z(1){
    t = (w == 200) ?     10:getchar();
  switch(t) {   case 0xa:
case EOF:       if(w--
){R(1[l ][0])
;for(i   =0,
p=e;i     <=w
;i+=     6){
R (     *p+
'+'     );*
p++     =0;
;}     R(
0xa   );w
  =-1 ;}p=
    e-       1;case
      32:     if (t<0) e(
0)     break; /*/*
  /*/     default : *
    p
    |=(001<<(w%6));
}if((++w%6)==0)p++;}e(
    0)}case 3:{O*u,*q,*x;U s[0400];
  i i;FILE*F; j:j=1;if(!(X=calloc(6<<
6,sizeof(O*)))) e(1) if(!(F=fopen(j[l],
    "r")))e(1)Z(fgets(s,j<<8,F))(*s)&&h(X,s+j,*s
    );j=b(i,=)&0xff;     i:u=0;x=X;
  Z(x){q=Y(*(   o)x)=Y(u)
=Y(x)=q;}       i[X]=u
;i=(i-2 +9)%(
sizeof   (s))
;if(i     ^j)
goto     i;;
y(F)     ; }
case     4:{
end     i i
;if     (!
X){   i=j
  =1; goto
    j;}       if(i){O
      **x     ,*m=*(x=X);
do*     x=1[x];Z(++
  x<X     +255);*x=m;
    }
    }default:if(!(t
=*2[l]++))break;case 0
    :{H p;i i,c,n;O *a;u:c=n=0;Z(c<
  10){c++b(;,n:n++)}if(n<='&'){c-=(n%
7);goto n;}else n++;a=*(X+t);Z(a){p=(H)
    a->L;Z(*p>=n){i=(*p++)-n;for(c=0;c<6;c++,i=i
    >>1){ if(b(!, i     &&)(*p >= n))
  break;R(32+   (i&1)*3);
}}R(10);a       =a->l;
}if(Q<2 )goto
D;if(*   l[2
]){R(     10)
;main     (4,
l);     }}}
Z(Q     ++<
1){     X+=
t;     if
((t   &7)
  >3) goto
    i;       else {
      t--     ;putchar(t)
;t     =(t&7)?t:t-
  '*'     ;}}exit(0);
    }
[/code]

[i](note: looks better viewed as text on the site; forum messes it up somewhat)
April 3, 2006, 9:24 PM
FrOzeN
Heh, enjoy debuging code like that. :P

Also, thanx @ MyndFyre. That clears up the terminology. I understood what was ment, I just worded myself incorrectly.
April 4, 2006, 4:16 AM

Search