Author | Message | Time |
---|---|---|
Myndfyr | Disclaimer: I do not claim to be a C or C++ expert -- as a matter of fact, I'm relatively lacking in knowledge, which is why I'm asking this question. I'm trying to understand the semantic differences between the typedef statement and #define. For instance, a LPSTR, or char* -- is there a difference at compile-time? In other words, are these two statements equvalent: [code] #define LPSTR char* [/code] [code] typedef char* LPSTR [/code] Also, can I say: [code] LPSTR lpszMyString = "foo.bar"; char* szString2 = lpszMyString; [/code] or do I have to cast? It seems to me that using typedefs is just a way of making the same thing be different from one another for reasons that seem to be beyond my comprehension (such as LPCSTR, LPCTSTR, LPSTR, etc.). Ultimately, aren't they all either char* or wchar_t*? TIA for the info :) This isn't any specific problem that I have, I'm just curious. | May 12, 2004, 12:35 AM |
Eli_1 | Every variable has a data type. typedef is used to define new data type names to [u]make a program more readable to the programmer.[/u] [code] int test = 0; typedef int dollars; dollars test2 = 1; int main() { test2 = test; return 0; }[/code] 'test' and 'test2' are EXACTLY the same to the compiler. But using the typedef 'dollars' will make the code easier to understand -- well not really, but you get the idea. | May 12, 2004, 12:53 AM |
Zeller | I actualy just read about this 2 days ago but ill try to help anway. #define works by replacing in the compiler what ever you set it as. [code] #define werd int myint; #define sayit cout << myint; int main() { werd; myint = 7; sayit; } [/code] typedef can only substitute definitions, usefull for long definitions like: [code] typedef unsigned short int werd; int main() { werd myint = 7; } [/code] I only started learning C++ last weak and I didnt test this code so it probably has some errors. but it should show the difference. Edit: tested both peaces of code and they work | May 12, 2004, 2:26 AM |
Eibro | [quote author=Myndfyre link=board=30;threadid=6762;start=0#msg59669 date=1084322123] Disclaimer: I do not claim to be a C or C++ expert -- as a matter of fact, I'm relatively lacking in knowledge, which is why I'm asking this question. I'm trying to understand the semantic differences between the typedef statement and #define. For instance, a LPSTR, or char* -- is there a difference at compile-time? In other words, are these two statements equvalent: [code] #define LPSTR char* [/code] [code] typedef char* LPSTR [/code] Also, can I say: [code] LPSTR lpszMyString = "foo.bar"; char* szString2 = lpszMyString; [/code] or do I have to cast? It seems to me that using typedefs is just a way of making the same thing be different from one another for reasons that seem to be beyond my comprehension (such as LPCSTR, LPCTSTR, LPSTR, etc.). Ultimately, aren't they all either char* or wchar_t*? TIA for the info :) This isn't any specific problem that I have, I'm just curious. [/quote]No, you don't need to cast. They're the same type. However, [code] #define LPSTR char* [/code] [code] typedef char* LPSTR [/code]aren't equivalent. Prefer the second. Example (assume #define is used) LPSTR var1, var2; In this case, var1 is of type char*, while var2 is of type char (whoah!) With the typedef, the expected occours, both var1 and var2 would be char*. Typedefs can also be a testament to portability, as well as readability. | May 12, 2004, 2:33 AM |
Mephisto | First, you need to understand how the preprocessor work. The compiler (which is what is important in this type of situation ;)) will never see your define, it will however see your typedef. First, examine the following declarations: [code] #define cities int typedef int cities; [/code] In the preprocesser define what happens is that wherever cities is seen in the source, it's simply replaced with the string "int" which is the actual built in type int to the compiler when it sees it. In the typedef, the compiler handles it. It makes cities an int, and treats it as an int where it is encountered (except in a string). You could in a sense think of a typedef as an object that is the same thing as the type you define it to. So, overall: Preprocessor defines: the type is automatically replaced wherever the define is encountered in the source and the compiler will see the type, not the name you defined it as. Typedefs: the name is made the type you make it by the compiler, so whatever the name of the typedef is, it's made the whatever type aswell. This all occurs at compile-time, and has nothing to do with the preprocessor or pre-compile time. | May 12, 2004, 3:27 AM |
Maddox | typedef defines types (hence the name), define is mostly used for macros and constants. | May 12, 2004, 6:06 AM |
Myndfyr | [quote author=Mephisto link=board=30;threadid=6762;start=0#msg59723 date=1084332426] First, you need to understand how the preprocessor work. The compiler (which is what is important in this type of situation ;)) will never see your define, it will however see your typedef. First, examine the following declarations: [code] #define cities int typedef int cities; [/code] In the preprocesser define what happens is that wherever cities is seen in the source, it's simply replaced with the string "int" which is the actual built in type int to the compiler when it sees it. In the typedef, the compiler handles it. It makes cities an int, and treats it as in int where it is encountered (except in a string). You could in a sense think of a typedef as an object that is the same thing as the type you define it to. So, overall: Preprocessor defines: the type is automatically replaced wherever the define is encountered in the source and the compiler will see the type, not the name you defined it as. Typedefs: the name is made the type you make it by the compiler, so whatever the name of the typedef is, it's made the whatever type aswell. This all occurs at compile-time, and has nothing to do with the preprocessor or pre-compile time. [/quote] Mephisto.... I understand how the pre-processor works, which is why I had the question. If I say: [code] #define LPSTR char* [/code] everywhere throughout the code where I have [code] LPSTR szStr; [/code] the compiler will see [code] char* szStr; [/code] The point of the question was, why is there a semantic difference between the two? The other crux of the question was, when I use typedef, in C++ -- being a strongly-typed language -- do I need to cast between them as they are different types, or can I just let them be? It's obvious I wouldn't have to with #define, but if typedef makes a new type...? [quote author=Eibro[yL] link=board=30;threadid=6762;start=0#msg59700 date=1084329209] Example (assume #define is used) LPSTR var1, var2; In this case, var1 is of type char*, while var2 is of type char (whoah!) With the typedef, the expected occours, both var1 and var2 would be char*. Typedefs can also be a testament to portability, as well as readability. [/quote] I thought the difference for pointer assignment depended on where the dereference operator was. Example: [code] char* szVar1, szVar2; // both are type char* char *szVar1, cVar2; // szVar1 is type char*, cVar2 is type char char * szVar1, szVar2; // ambiguous case, bad practice [/code] No? | May 12, 2004, 6:06 PM |
Eibro | [quote]I thought the difference for pointer assignment depended on where the dereference operator was. Example: [code] char* szVar1, szVar2; // both are type char* char *szVar1, cVar2; // szVar1 is type char*, cVar2 is type char char * szVar1, szVar2; // ambiguous case, bad practice [/code] No? [/quote]No. In all three instances szVar1 would be char*, where szVar2 would be char. | May 12, 2004, 6:31 PM |
Eli_1 | White space is ignored by the compiler. The placement won't make a difference. | May 12, 2004, 6:43 PM |
Mephisto | The point I was making was how it worked to an extent. As for your question, the reason there is a difference between the two, IIRC, is because typedef did not exist in C, and only the preprocessor defines were avaliable. When C++ came along it put an end to that with typedefs aswell as type-constants. As far as I know, you don't need to make a typecast if you have a typedef...But I'm not sure if I understood your question about the typecasting. Also, typedefs and preprocessor defines are completely different. As I pointed out, the defines are done at preprocessor time and then used at compile-time after string substitution. Typdefs are handled at compile-time and are made into the type int, so it's as if your typedef is a built in type for whatever you assigned it to while in the scope in your program. It's all handled at compile-time. | May 12, 2004, 6:59 PM |
Eli_1 | You don't have to typecast. [code] int blah; // and typedef dec int; dec blah; [/code] Are exactly the same. | May 12, 2004, 7:11 PM |
Mephisto | If your question about casts was that you could typecast a typedef, then yes, as you could any other type. | May 12, 2004, 9:44 PM |
Raven | [quote author=Eli_1 link=board=30;threadid=6762;start=0#msg59819 date=1084387380] White space is ignored by the compiler. The placement won't make a difference. [/quote] That is not so. The compiler let's you get away with alot of "whitespace naughtiness", however, the preprocessor is not so leanient. ;) | May 13, 2004, 1:16 AM |
Adron | [quote author=Mephisto link=board=30;threadid=6762;start=0#msg59854 date=1084398263] If your question about casts was that you could typecast a typedef, then yes, as you could any other type. [/quote] But you don't have to cast between typedefs that amount to the same thing. They save typing, that's all. Some things can be tricky to type and require lots of paranthesing without typedefs, say for example array[10] of pointers to array[15]s of functions taking ints for arguments and returning pointers to arrays[5] of pointers to ints. Which would be something like: typedef int *arrayofintptr[5]; typedef arrayofintptr *(*funcptr)(int); typedef funcptr funcarray[15]; funcarray *myarray[10]; vs. int *(*(*(*myarray2[10])[15])(int))[5]; | May 13, 2004, 1:23 AM |
Eli_1 | [quote author=Adron link=board=30;threadid=6762;start=0#msg59908 date=1084411394] But you don't have to cast between typedefs that amount to the same thing. They save typing, that's all. Some things can be tricky to type and require lots of paranthesing without typedefs, say for example array[10] of pointers to array[15]s of functions taking ints for arguments and returning pointers to arrays[5] of pointers to ints. Which would be something like: typedef int *arrayofintptr[5]; typedef arrayofintptr *(*funcptr)(int); typedef funcptr funcarray[15]; funcarray *myarray[10]; vs. int *(*(*(*myarray2[10])[15])(int))[5]; [/quote] I have a lot to learn... ::) | May 13, 2004, 1:31 AM |
Mephisto | It's not hard to comprehend if you actually take a minute to think about what an array/pointer is... Also, it might be helpful for you when you get into more advanced C/C++ programming which uses a heavy use of pointers and references, just keep logically in mind where the pointer is pointing to. Also, as Raven pointed out the preprocessor has policy against whitespace. ;) It has an entirely different syntax and is not part of the C/C++ language IIRC. An example of whitespace violation would be in the use of defining macro functions: #define theMacro(x, y) x + y v.s. #define theMacro (x, y) x + y The first declaration is in fact a macro function which takes in arguments x and y and adds them together. The second declaration is really a constant because of your whitespace violation. Wherever theMacro is seen, it will be replaced with the string "(x, y) x + y". This also suggests that the preprocessor essentially doesn't really care about whitespace...but you do get different results based on your whitespaces, and even parenthasis with macro functions (but just as anything in C/C++). | May 13, 2004, 2:50 AM |
Myndfyr | [quote author=Mephisto link=board=30;threadid=6762;start=0#msg59821 date=1084388366] The point I was making was how it worked to an extent. As for your question, the reason there is a difference between the two, IIRC, is because typedef did not exist in C, and only the preprocessor defines were avaliable. [/quote] Nope. Mephisto, learn about the features of C. You'll find there are many that happen to be in C++. | May 29, 2004, 7:01 PM |
Maddox | [quote author=Myndfyre link=board=30;threadid=6762;start=15#msg62642 date=1085857296] [quote author=Mephisto link=board=30;threadid=6762;start=0#msg59821 date=1084388366] The point I was making was how it worked to an extent. As for your question, the reason there is a difference between the two, IIRC, is because typedef did not exist in C, and only the preprocessor defines were avaliable. [/quote] Nope. Mephisto, learn about the features of C. You'll find there are many that happen to be in C++. [/quote] https://davnit.net/bnet/vL/phpbbs/index.php?board=30;action=display;threadid=6496;start=msg57077#msg57077 | May 29, 2004, 7:18 PM |