• Welcome to Valhalla Legends Archive.
 

Pointer Syntax Opinions

Started by FrOzeN, March 31, 2006, 10:10 PM

Previous topic - Next topic

FrOzeN

int main(int argc, HERE) {
    return 0;
}


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


  • char* argv[]
  • char *argv[]
  • char** argv
  • char **argv
  • Others..?

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]
~ FrOzeN

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[][]
Grif: Yeah, and the people in the red states are mad because the people in the blue states are mean to them and want them to pay money for roads and schools instead of cool things like NASCAR and shotguns.  Also, there's something about ketchup in there.

Kp

Quote from: rabbit on April 01, 2006, 09:05 AM
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[][]

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.
[19:20:23] (BotNet) <[vL]Kp> Any idiot can make a bot with CSB, and many do!

K

Quote from: rabbit on April 01, 2006, 09:05 AM
char** should give errors...I usually write it as char **argv.

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:


// 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.




rabbit

Ok then.  Something is learned every day.
Grif: Yeah, and the people in the red states are mad because the people in the blue states are mean to them and want them to pay money for roads and schools instead of cool things like NASCAR and shotguns.  Also, there's something about ketchup in there.

FrOzeN

Quote from: Kp on April 01, 2006, 10:03 AM
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.
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. :)
~ FrOzeN

rabbit

You should remember that an unsized array is a pointer: they are interchangable.
Grif: Yeah, and the people in the red states are mad because the people in the blue states are mean to them and want them to pay money for roads and schools instead of cool things like NASCAR and shotguns.  Also, there's something about ketchup in there.

MyndFyre

Quote from: FrOzeN on April 03, 2006, 02:42 AM
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. :)
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 from: K on April 01, 2006, 02:23 PM
Many people prefer to put the pointer or reference indicator next to the variable rather than the type for this reason:


char *a, b; // this placement clarifies that only a is a pointer.

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 from: FrOzeN on April 03, 2006, 02:42 AM
That way it clearly shows it's an array, aswell as showing that argv is the pointer
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:

int main(int argc, char** argv);

...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:

#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;
    }
}

Run it from a command line and include some arguments after it.  The output would be the same as this program:

#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;
    }
}


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.  ;)
QuoteEvery generation of humans believed it had all the answers it needed, except for a few mysteries they assumed would be solved at any moment. And they all believed their ancestors were simplistic and deluded. What are the odds that you are the first generation of humans who will understand reality?

After 3 years, it's on the horizon.  The new JinxBot, and BN#, the managed Battle.net Client library.

Quote from: chyea on January 16, 2009, 05:05 PM
You've just located global warming.

dxoigmn

Quote from: MyndFyre[vL] on April 03, 2006, 11:36 AM
Quote from: K on April 01, 2006, 02:23 PM
Many people prefer to put the pointer or reference indicator next to the variable rather than the type for this reason:


char *a, b; // this placement clarifies that only a is a pointer.


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.

Yes it does. A quick glance at K&R says a is a pointer and b is not. There is no ambiguity.

MyndFyre

Quote from: dxoigmn on April 03, 2006, 01:49 PM
Yes it does. A quick glance at K&R says a is a pointer and b is not. There is no ambiguity.

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.
QuoteEvery generation of humans believed it had all the answers it needed, except for a few mysteries they assumed would be solved at any moment. And they all believed their ancestors were simplistic and deluded. What are the odds that you are the first generation of humans who will understand reality?

After 3 years, it's on the horizon.  The new JinxBot, and BN#, the managed Battle.net Client library.

Quote from: chyea on January 16, 2009, 05:05 PM
You've just located global warming.

Adron

#10
On the topic of placement of whitespace, check out iocc for code like this:


#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[i];
   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);
    }


(note: looks better viewed as text on the site; forum messes it up somewhat)

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.
~ FrOzeN