From: Wolfgang Lorenz on 4 Jan 2010 04:20 This works fine with VC5. The cast allows me to concentrate on my algorithm and not having to worry about if the array contains real data or just pointers to it. But when compiling with VC2008, I get 3 warnings: (30) : warning C4700: uninitialized local variable 'i_ref' used (35) : warning C4700: uninitialized local variable 'i_ptr' used (47) : warning C4700: uninitialized local variable 'i_ref' used And it works only in release mode. With _DEBUG enabled, it stops with a runtime error :( -- Wolfgang // make loop counter local to prevent error C2374 with old compilers #if _MSC_VER <= 1200 // behaviour unknown for VC6 < version < VC2005 #define for if (1) for #endif #include <stdio.h> template<class T> inline T& cast_to(T&, T& x) { return x; } template<class T> inline T& cast_to(T&, T* x) { return *x; } template<class T> inline T* cast_to(T*, T& x) { return &x; } #define lengthof(a) (sizeof(a) / sizeof(a[0])) #define foreach(e, T, a) for (int e##i = 0; e##i < lengthof(a); e##i++) { T e = cast_to(e, (a)[e##i]); /##/ int is[] = { 1, 2, 3 }; int* pis[] = { &is[2], &is[1], &is[0] }; void main() { printf("\n\nIterating through the data:\n"); printf("\nforeach (i_cpy, int , is) ="); foreach (i_cpy, int , is) { printf(" %d", i_cpy); } printf("\nforeach (i_ref, int&, is) ="); foreach (i_ref, int&, is) { printf(" %d", i_ref); } printf("\nforeach (i_ptr, int*, is) ="); foreach (i_ptr, int*, is) { printf(" %d", *i_ptr); } printf("\n\nIterating through the pointers:\n"); printf("\nforeach (i_cpy, int , pis) ="); foreach (i_cpy, int , pis) { printf(" %d", i_cpy); } printf("\nforeach (i_ref, int&, pis) ="); foreach (i_ref, int&, pis) { printf(" %d", i_ref); } printf("\nforeach (i_ptr, int*, pis) ="); foreach (i_ptr, int*, pis) { printf(" %d", *i_ptr); } printf("\n\nREADY.\n"); getchar(); }
From: Ike Naar on 4 Jan 2010 05:36 In article <4b41b2dc$0$6590$9b4e6d93(a)newsspool3.arcor-online.net>, Wolfgang Lorenz <wl924236(a)arcor.de> wrote: >This works fine with VC5. The cast allows me to concentrate on my >algorithm and not having to worry about if the array contains real data >or just pointers to it. > >But when compiling with VC2008, I get 3 warnings: > >(30) : warning C4700: uninitialized local variable 'i_ref' used >(35) : warning C4700: uninitialized local variable 'i_ptr' used >(47) : warning C4700: uninitialized local variable 'i_ref' used > >And it works only in release mode. With _DEBUG enabled, it stops with a >runtime error :( > >-- Wolfgang > >// make loop counter local to prevent error C2374 with old compilers >#if _MSC_VER <= 1200 // behaviour unknown for VC6 < version < VC2005 > #define for if (1) for >#endif What is the purpose of this macro? >#include <stdio.h> > >template<class T> inline T& cast_to(T&, T& x) { return x; } >template<class T> inline T& cast_to(T&, T* x) { return *x; } >template<class T> inline T* cast_to(T*, T& x) { return &x; } > >#define lengthof(a) (sizeof(a) / sizeof(a[0])) >#define foreach(e, T, a) for (int e##i = 0; e##i < lengthof(a); e##i++) >{ T e = cast_to(e, (a)[e##i]); /##/ There are a few problems with this macro, and as a result, your code does not even compile on my machine. 1) Apparently the #define foreach text is supposed to be the rest of the line followed by the next line; that means the newline at the end of the first line should be escaped with a backslash: #define foreach(e, T, a) for (int e##i = 0; e##i < lengthof(a); e##i++) \ { T e = cast_to(e, (a)[e##i]); /##/ 2) The text of this macro contains an opening brace, but not the matching closing brace; probably the caller of the macro is expected to provide the closing brace. But, later on in the program, the macro calls are followed by both an opening brace and a closing brace, as a result the braces at the call sites don't match. 3) What is the purpose of the /##/ construct? My compiler (gcc) does not accept it. If I fix these problems (i.e. add the backslash, remove the spurious opening brace at the call sites, and remove the /##/) then the program compiles and seems to run okay. >int is[] = { 1, 2, 3 }; > >int* pis[] = { &is[2], &is[1], &is[0] }; > >void main() { > > printf("\n\nIterating through the data:\n"); > > printf("\nforeach (i_cpy, int , is) ="); > foreach (i_cpy, int , is) { > printf(" %d", i_cpy); > } > > printf("\nforeach (i_ref, int&, is) ="); > foreach (i_ref, int&, is) { > printf(" %d", i_ref); > } > > printf("\nforeach (i_ptr, int*, is) ="); > foreach (i_ptr, int*, is) { > printf(" %d", *i_ptr); > } > > printf("\n\nIterating through the pointers:\n"); > > printf("\nforeach (i_cpy, int , pis) ="); > foreach (i_cpy, int , pis) { > printf(" %d", i_cpy); > } > > printf("\nforeach (i_ref, int&, pis) ="); > foreach (i_ref, int&, pis) { > printf(" %d", i_ref); > } > > printf("\nforeach (i_ptr, int*, pis) ="); > foreach (i_ptr, int*, pis) { > printf(" %d", *i_ptr); > } > > printf("\n\nREADY.\n"); > getchar(); >} Here's the output: Iterating through the data: foreach (i_cpy, int , is) = 1 2 3 foreach (i_ref, int&, is) = 1 2 3 foreach (i_ptr, int*, is) = 1 2 3 Iterating through the pointers: foreach (i_cpy, int , pis) = 3 2 1 foreach (i_ref, int&, pis) = 3 2 1 foreach (i_ptr, int*, pis) = 3 2 1 READY.
From: Ike Naar on 4 Jan 2010 07:01 In article <4b41b2dc$0$6590$9b4e6d93(a)newsspool3.arcor-online.net>, Wolfgang Lorenz <wl924236(a)arcor.de> wrote: >This works fine with VC5. The cast allows me to concentrate on my >algorithm and not having to worry about if the array contains real data >or just pointers to it. > >But when compiling with VC2008, I get 3 warnings: > >(30) : warning C4700: uninitialized local variable 'i_ref' used >(35) : warning C4700: uninitialized local variable 'i_ptr' used >(47) : warning C4700: uninitialized local variable 'i_ref' used > >And it works only in release mode. With _DEBUG enabled, it stops with a >runtime error :( > >-- Wolfgang > >// make loop counter local to prevent error C2374 with old compilers >#if _MSC_VER <= 1200 // behaviour unknown for VC6 < version < VC2005 > #define for if (1) for >#endif > >#include <stdio.h> Do you realize that the ``#define for'' may alter the semantics of for statements that appear later in the code? E.g. those in <stdio.h> ? For example, suppose you have the following: if (condition) for (/*whatever*/) do_a; else do_b; If condition is false, this for statement should normally execute do_b. Now see what happens when ``for'' is redefined as ``if (1) for''. The code becomes: if (condition) if (1) for (/*whatever*/) do_a; else do_b; The indentation is now misleading, so let's fix it: if (condition) if (1) for (/*whatever*/) do_a; else do_b; Now, you see that when condition is false, do_b is *not* executed anymore. My advice is to remove the ``for'' macro, or, at least don't place it before any #include lines.
From: Wolfgang Lorenz on 4 Jan 2010 09:13 Hi Ike, the purpose of the macro: #define for if (1) for is to make the loop counter local on Microsoft Visual C++ 5 from 1997. Without it, this code would not compile: for (int i = 0; i < 10; i++); for (int i = 0; i < 10; i++); Visual C++ 5 makes i to scope outside the for loop, and then the second definition of i leads to a "variable already defined" error. This behaviour has been changed in later versions of the compiler, therfore the version check for _MSC_VER <= 1200. You are right, it should not be defined before the #include <stdio.h> line. In real programs, I use it as a part of a private include file which is always included after the standard include files have been included. > 1) Apparently the #define foreach text is supposed to be the > rest of the line followed by the next line; that means the > newline at the end of the first line should be escaped with a > backslash Oops, this line break has been inserted by the news posting program. It is a single line in the source file. > 2) The text of this macro contains an opening brace, but not the > matching closing brace ... > 3) What is the purpose of the /##/ construct? To mask out the rest of the line ;) foreach (i, int, is) { ... } will be translated into: for (int ii = ...) ... { // { ... } I know, it is dangerous, but I found no other way to keep the balance between the braces. > My compiler (gcc) does not accept it. Sorry to hear that. I use mostly fast Visual C++ 5, sometimes slow Visual C++ 2008 and very rarely Intel C++ 9. > If I fix these problems (i.e. add the backslash, remove the spurious > opening brace at the call sites, and remove the /##/) then the program > compiles and seems to run okay. Obviously, gcc does not have these safety checks like Visual C++ 2008. But because /##/ does not work with gcc, there is no more balance between the braces. > My advice is to remove the ``for'' macro, or, at least don't place > it before any #include lines. This message translates into: "Throw away your old Visual C++ 5 from 1997 and use something newer!" Well, maybe I would -- but it is fast, has everything I need, doesn't go online when I press F1 -- and I paid for it when I was a professional developer a long time ago. Today I don't even have a DSL line, so there is no big file downloading. My hope was that the template wizards know of another way which does not depend on the uninitialized first parameter in the cast_to() function. -- Wolfgang
From: Ben Bacarisse on 4 Jan 2010 12:35 Wolfgang Lorenz <wl924236(a)arcor.de> writes: <snip> >> 2) The text of this macro contains an opening brace, but not the >> matching closing brace ... >> 3) What is the purpose of the /##/ construct? > > To mask out the rest of the line ;) > > foreach (i, int, is) { > ... > } > > will be translated into: > > for (int ii = ...) ... { // { > ... > } > > I know, it is dangerous, but I found no other way to keep the balance > between the braces. > >> My compiler (gcc) does not accept it. > > Sorry to hear that. I use mostly fast Visual C++ 5, sometimes slow > Visual C++ 2008 and very rarely Intel C++ 9. And I am sorry to hear that! So many compilers that don't get it right even though the same rules have applied for many, many, years: comments are removed before macros are expanded. Once macro expansion has happened, no comments will be removed. This is the same in C and C++ and it has been the rule in C for 20 years. I doubt there has been a C++ standard that had a different rule, though I don't have enough old versions to go and check the full history. Of course, you might be asking for this non-standard behaviour explicitly but that is also risky. Are you sure the non-standard behaviour won't change in the future? <snip> -- Ben.
|
Next
|
Last
Pages: 1 2 3 Prev: Is it possible that compilers or projects have bugs? Next: STL for a C programmer |