* type Foo_ptr in new void*; @ 2001-07-29 4:31 Tomasz Wegrzanowski 2001-07-29 5:56 ` tmoran 2001-07-29 14:12 ` Florian Weimer 0 siblings, 2 replies; 19+ messages in thread From: Tomasz Wegrzanowski @ 2001-07-29 4:31 UTC (permalink / raw) I want to use C library from Ada. C function/procedures are like: Foo *foo_new(some args); void foo_delete(Foo*); void foo_some_operation(Foo*,some args); xyz foo_some_function(Foo*,some args); Of course gc is by hand. How should I typedef Foo* ? ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: type Foo_ptr in new void*; 2001-07-29 4:31 type Foo_ptr in new void*; Tomasz Wegrzanowski @ 2001-07-29 5:56 ` tmoran 2001-07-29 8:57 ` Tomasz Wegrzanowski 2001-07-29 14:12 ` Florian Weimer 1 sibling, 1 reply; 19+ messages in thread From: tmoran @ 2001-07-29 5:56 UTC (permalink / raw) > Foo *foo_new(some args); > void foo_delete(Foo*); > void foo_some_operation(Foo*,some args); > xyz foo_some_function(Foo*,some args); > > How should I typedef Foo* ? Presumably you "typedef Foo" in the C code in normal C style. If you are wondering how to describe these C functions in Ada, from the implementation advice in ARM B.3(67 .. 70), as given at www.adapower.com: 4.An Ada in parameter of an access-to-object type with designated type T is passed as a t* argument to a C function, where t is the C type corresponding to the Ada type T. 5.An Ada access T parameter, or an Ada out or in out parameter of an elementary type T, is passed as a t* argument to a C function, where t is the C type corresponding to the Ada type T. In the case of an elementary out or in out parameter, a pointer to a temporary copy is used to preserve by-copy semantics. 6.An Ada parameter of a record type T, of any mode, is passed as a t* argument to a C function, where t is the C struct corresponding to the Ada type T. 7.An Ada parameter of an array type with component type T, of any mode, is passed as a t* argument to a C function, where t is the C type corresponding to the Ada type T. So given type Foo is record ... type Foo_Pointer is access Foo; > Foo *foo_new(some args); function foo_new(someargs : sometype) return Foo_Pointer; > void foo_delete(Foo*); procedure foo_delete(Param : in out Foo); > void foo_some_operation(Foo*,some args); procedure foo_some_operation(Param : in out Foo; someargs : in sometype); > xyz foo_some_function(Foo*,some args); function foo_some_function(P : Foo_Pointer; someargs : sometype) return xyz; There are other ways, for instance procedure foo_delete(Param : access Foo); ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: type Foo_ptr in new void*; 2001-07-29 5:56 ` tmoran @ 2001-07-29 8:57 ` Tomasz Wegrzanowski 2001-07-29 12:26 ` Marc A. Criley 2001-07-29 13:40 ` Dale Stanbrough 0 siblings, 2 replies; 19+ messages in thread From: Tomasz Wegrzanowski @ 2001-07-29 8:57 UTC (permalink / raw) In article <TzN87.10780$Kd7.6085799@news1.rdc1.sfba.home.com>, tmoran@acm.org wrote: > So given > type Foo is record ... > type Foo_Pointer is access Foo; I can't do this. Foo is supposed to be used only as a pointer. I don't know if newer version of library will use the same Foo. ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: type Foo_ptr in new void*; 2001-07-29 8:57 ` Tomasz Wegrzanowski @ 2001-07-29 12:26 ` Marc A. Criley 2001-07-30 1:05 ` Tomasz Wegrzanowski 2001-07-29 13:40 ` Dale Stanbrough 1 sibling, 1 reply; 19+ messages in thread From: Marc A. Criley @ 2001-07-29 12:26 UTC (permalink / raw) Tomasz Wegrzanowski wrote: > > In article <TzN87.10780$Kd7.6085799@news1.rdc1.sfba.home.com>, tmoran@acm.org wrote: > > So given > > type Foo is record ... > > type Foo_Pointer is access Foo; > > I can't do this. > Foo is supposed to be used only as a pointer. > I don't know if newer version of library will use the same Foo. In tmoran's post, wherever you saw "in out Foo", change it to "in Foo_Pointer". In order to declare a pointer to a type, you have to have that type's definition. Even C requires that for "foo*" there be some declaration of "foo". Marc A. Criley Senior Staff Engineer Quadrus Corporation www.quadrus.com ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: type Foo_ptr in new void*; 2001-07-29 12:26 ` Marc A. Criley @ 2001-07-30 1:05 ` Tomasz Wegrzanowski 2001-07-30 1:20 ` tmoran 2001-07-30 2:09 ` James Rogers 0 siblings, 2 replies; 19+ messages in thread From: Tomasz Wegrzanowski @ 2001-07-30 1:05 UTC (permalink / raw) In article <3B63F48A.2E2642C6@earthlink.net>, Marc A. Criley wrote: >> I can't do this. >> Foo is supposed to be used only as a pointer. >> I don't know if newer version of library will use the same Foo. > > In tmoran's post, wherever you saw "in out Foo", change it to "in > Foo_Pointer". > > In order to declare a pointer to a type, you have to have that type's > definition. Even C requires that for "foo*" there be some declaration > of "foo". Not true. You can use `struct Foo *' without declaring `struct Foo'. You can `typedef struct Foo Foo_t;' or `typedef struct Foo *Foo_p;' and use Foo_t and Foo_p w/o declaring `struct Foo'. ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: type Foo_ptr in new void*; 2001-07-30 1:05 ` Tomasz Wegrzanowski @ 2001-07-30 1:20 ` tmoran 2001-07-30 2:09 ` James Rogers 1 sibling, 0 replies; 19+ messages in thread From: tmoran @ 2001-07-30 1:20 UTC (permalink / raw) type Foo_ptr is new Interfaces.C.Strings.chars_ptr; >You can use `struct Foo *' without declaring `struct Foo'. That's like type Foo; type Foo_Pointer is access Foo; except that in Ada you would need a full declaration of Foo eventually. In any case, clearly if you don't know the structure of a Foo, but only pass around pointers to them, then the suggestion type Foo_ptr is new Interfaces.C.Strings.chars_ptr; seems to fit. Any problems with that? ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: type Foo_ptr in new void*; 2001-07-30 1:05 ` Tomasz Wegrzanowski 2001-07-30 1:20 ` tmoran @ 2001-07-30 2:09 ` James Rogers 2001-07-30 2:36 ` Warren W. Gay VE3WWG ` (2 more replies) 1 sibling, 3 replies; 19+ messages in thread From: James Rogers @ 2001-07-30 2:09 UTC (permalink / raw) Tomasz Wegrzanowski wrote: > > In article <3B63F48A.2E2642C6@earthlink.net>, Marc A. Criley wrote: > >> I can't do this. > >> Foo is supposed to be used only as a pointer. > >> I don't know if newer version of library will use the same Foo. > > > > In tmoran's post, wherever you saw "in out Foo", change it to "in > > Foo_Pointer". > > > > In order to declare a pointer to a type, you have to have that type's > > definition. Even C requires that for "foo*" there be some declaration > > of "foo". > > Not true. > You can use `struct Foo *' without declaring `struct Foo'. > You can `typedef struct Foo Foo_t;' or `typedef struct Foo *Foo_p;' > and use Foo_t and Foo_p w/o declaring `struct Foo'. Yes, you are correct. C does allow you to forward declare a structure or a pointer without ever completing the definition. This is one of the nasty capabilities "provided" by C. You can even create an array of Foo *. However, pointer arithmetic from the start of this array produces unspecified behavior. What is the sizeof Foo? Since it is undefined, there is no correct answer to that question. Without a proper definition of the sizeof Foo, there can be no reliable pointer arithmetic. In other words, you can declare some wonderful data structures in C based on incomplete type definitions. Unfortunately, a program built upon such a structure is neither reliable nor portable. Ada does not allow you to compile a program with an incomplete type definition. There is no equivalent because the existence of an equivalent to this C capability would only introduce errors in your program. There is nothing positive that can be achieved by allowing a program to be incompletely specified. I first realized the differences between C and Ada in this respect when first learning Ada to support the development of debuggers for in circuit emulators in 1994. I had to produce programs exhibiting every data type you can produce from each language so that the symbolic debug output of compilers, and recognition of the debuggers could be verified. There was never a version of Ada that supported incomplete type definition. Jim Rogers Colorado Springs, Colorado USA ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: type Foo_ptr in new void*; 2001-07-30 2:09 ` James Rogers @ 2001-07-30 2:36 ` Warren W. Gay VE3WWG 2001-07-30 3:10 ` James Rogers 2001-07-31 1:21 ` Tomasz Wegrzanowski 2001-07-31 4:56 ` Darren New 2 siblings, 1 reply; 19+ messages in thread From: Warren W. Gay VE3WWG @ 2001-07-30 2:36 UTC (permalink / raw) James Rogers wrote: > Tomasz Wegrzanowski wrote: > > In article <3B63F48A.2E2642C6@earthlink.net>, Marc A. Criley wrote: > > >> I can't do this. > > >> Foo is supposed to be used only as a pointer. > > >> I don't know if newer version of library will use the same Foo. > > > > > > In tmoran's post, wherever you saw "in out Foo", change it to "in > > > Foo_Pointer". > > > > > > In order to declare a pointer to a type, you have to have that type's > > > definition. Even C requires that for "foo*" there be some declaration > > > of "foo". > > > > Not true. > > You can use `struct Foo *' without declaring `struct Foo'. > > You can `typedef struct Foo Foo_t;' or `typedef struct Foo *Foo_p;' > > and use Foo_t and Foo_p w/o declaring `struct Foo'. > > Yes, you are correct. C does allow you to forward declare a structure > or a pointer without ever completing the definition. This is one of > the nasty capabilities "provided" by C. You can even create an array > of Foo *. However, pointer arithmetic from the start of this array > produces unspecified behavior. What is the sizeof Foo? Since it is > undefined, there is no correct answer to that question. Without a > proper definition of the sizeof Foo, there can be no reliable pointer > arithmetic. I don't think your "unspecified behavior" assertion is truly fair here. I believe that when you reach a point in the C/C++ compile where pointer arithmetic is required on the "undefined type", you will get a compile error. The compiler will not generate code that does "undefined behaviour" here. If there is any further doubt about it, I am sure this can be tested with a short example program. > In other words, you can declare some wonderful data structures in C > based on incomplete type definitions. Unfortunately, a program built > upon such a structure is neither reliable nor portable. Sad, but true. What sometimes happens, is that the C programmer wants the application to see an "opaque type", and so presents a different type to the user (by include file) than the original structure. If this "proxy" is incorrectly defined, its size can be wrong, causing of course, much "havoc" under the right circumstances. Ada of course, provides a better model for visibility. > Ada does not allow you to compile a program with an incomplete type > definition. There is no equivalent because the existence of an > equivalent to this C capability would only introduce errors in your > program. There is nothing positive that can be achieved by allowing > a program to be incompletely specified. Ada does permit you to define an incomplete type as well, but the condition is that it must be defined eventually. I agree that enforcing its later definition, is a good thing. -- Warren W. Gay VE3WWG http://members.home.net/ve3wwg ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: type Foo_ptr in new void*; 2001-07-30 2:36 ` Warren W. Gay VE3WWG @ 2001-07-30 3:10 ` James Rogers 2001-07-31 2:14 ` Warren W. Gay VE3WWG 0 siblings, 1 reply; 19+ messages in thread From: James Rogers @ 2001-07-30 3:10 UTC (permalink / raw) "Warren W. Gay VE3WWG" wrote: > > I don't think your "unspecified behavior" assertion is truly fair here. > I believe that when you reach a point in the C/C++ compile where > pointer arithmetic is required on the "undefined type", you will get > a compile error. The compiler will not generate code that does > "undefined behaviour" here. If there is any further doubt about it, > I am sure this can be tested with a short example program. Your assertion may be true for C++ compilers, but it was not true for C compilers in the early 1990s. > Ada does permit you to define an incomplete type as well, but the > condition is that it must be defined eventually. I agree that enforcing > its later definition, is a good thing. Let's be a little more precise here. Ada does not allow you to define incomplete types. It allows you to define unconstrained types. There is a real difference. All Ada objects are fully defined. You cannot make an unconstrained instance of an unconstrained type. Jim Rogers Colorado Springs, Colorado USA ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: type Foo_ptr in new void*; 2001-07-30 3:10 ` James Rogers @ 2001-07-31 2:14 ` Warren W. Gay VE3WWG 0 siblings, 0 replies; 19+ messages in thread From: Warren W. Gay VE3WWG @ 2001-07-31 2:14 UTC (permalink / raw) James Rogers wrote: > "Warren W. Gay VE3WWG" wrote: > > > > I don't think your "unspecified behavior" assertion is truly fair here. > > I believe that when you reach a point in the C/C++ compile where > > pointer arithmetic is required on the "undefined type", you will get > > a compile error. The compiler will not generate code that does > > "undefined behaviour" here. If there is any further doubt about it, > > I am sure this can be tested with a short example program. > > Your assertion may be true for C++ compilers, but it was not true > for C compilers in the early 1990s. I've been using C for a long time, and I've used a number of C compilers. In that experience, I've never seen it compile pointer arithmetic on non-defined pointer types (you'll get a compiler error at the point where the arithmetic is required). If you can site a specific example, I might believe it. Even then, I'd have to say that it was unusual and attributable to a bad C compiler. > > Ada does permit you to define an incomplete type as well, but the > > condition is that it must be defined eventually. I agree that enforcing > > its later definition, is a good thing. > > Let's be a little more precise here. Ada does not allow you to define > incomplete types. You know what I meant. However, for everyone else, here is precisely what I was trying to describe: package X is type My_Type; -- Not fully defined.... type My_Type_Ptr is access all My_Type; -- Here My_Type is still _not_ defined yet... type My_Type is record Name : String(1..8); Next : My_Type_Ptr; -- Ptr to next end record; end X; Between the statement "type My_Type;" and the full declaration at the bottom, like C, you can have a forward referencing type, where it is not fully defined. Note that in this case, there is no other way to define the My_Type_Ptr member Next in My_Type. This is why it is permitted. -- Warren W. Gay VE3WWG http://members.home.net/ve3wwg ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: type Foo_ptr in new void*; 2001-07-30 2:09 ` James Rogers 2001-07-30 2:36 ` Warren W. Gay VE3WWG @ 2001-07-31 1:21 ` Tomasz Wegrzanowski 2001-07-31 3:06 ` James Rogers 2001-07-31 4:56 ` Darren New 2 siblings, 1 reply; 19+ messages in thread From: Tomasz Wegrzanowski @ 2001-07-31 1:21 UTC (permalink / raw) In article <3B64C26F.C195B4E0@worldnet.att.net>, James Rogers wrote: > Yes, you are correct. C does allow you to forward declare a structure > or a pointer without ever completing the definition. This is one of > the nasty capabilities "provided" by C. You can even create an array > of Foo *. However, pointer arithmetic from the start of this array > produces unspecified behavior. What is the sizeof Foo? Since it is > undefined, there is no correct answer to that question. Without a > proper definition of the sizeof Foo, there can be no reliable pointer > arithmetic. Correct answer is compilation error. It's illegal to do pointer arith on void* or incomplete types. > In other words, you can declare some wonderful data structures in C > based on incomplete type definitions. Unfortunately, a program built > upon such a structure is neither reliable nor portable. It's both portable and reliable. > Ada does not allow you to compile a program with an incomplete type > definition. There is no equivalent because the existence of an > equivalent to this C capability would only introduce errors in your > program. There is nothing positive that can be achieved by allowing > a program to be incompletely specified. Sure, if your favourite language has no feature X, then feature X is useless. Incomplete types warrant opacity. ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: type Foo_ptr in new void*; 2001-07-31 1:21 ` Tomasz Wegrzanowski @ 2001-07-31 3:06 ` James Rogers 2001-07-31 5:02 ` Warren W. Gay VE3WWG 2001-07-31 7:22 ` Florian Weimer 0 siblings, 2 replies; 19+ messages in thread From: James Rogers @ 2001-07-31 3:06 UTC (permalink / raw) Tomasz Wegrzanowski wrote: > > In article <3B64C26F.C195B4E0@worldnet.att.net>, James Rogers wrote: > > Yes, you are correct. C does allow you to forward declare a structure > > or a pointer without ever completing the definition. This is one of > > the nasty capabilities "provided" by C. You can even create an array > > of Foo *. However, pointer arithmetic from the start of this array > > produces unspecified behavior. What is the sizeof Foo? Since it is > > undefined, there is no correct answer to that question. Without a > > proper definition of the sizeof Foo, there can be no reliable pointer > > arithmetic. > > Correct answer is compilation error. > It's illegal to do pointer arith on void* or incomplete types. It is illegal, but not necessarily caught by the compiler. This means that the correct answer is not compilation error. C compilers are actually pretty primitive in their understanding of data type completion. They rely on highly intelligent linkers to find all the completions. Unfortunately, linker diagnostic messages are a lot less useful than compiler diagnostic messages. One reason is that the linker has no understanding of source code line numbers. It cannot tell you where the problem occured beyond the name of the object file it came from. Given the C #include technology, you cannot even directly relate the object file name with the source file name in all cases. A single object file could have been created from one or several source files. Even more problems arise when using shared libraries or DLLs. In that case the linker cannot find all the required pieces. Only the program loader will find them. Your compiler and linker may execute without error. Your loader will be left to try to identify all the missing pieces. Loader error messages are even poorer than linker error messages. What does it mean, then, when a function returns a void*? You are allowed to cast that void* to any other pointer type you want. Once cast, you are allowed to perform pointer arithmetic on it. If you do not TRULY know the type of the data pointed to by a void*, and then you cast it to some type, expecting correct results, you will sometimes get a nasty surprise. Pointer arithmetic will be performed, but your view of the data will be incorrect due to poor alignment problems. > > > In other words, you can declare some wonderful data structures in C > > based on incomplete type definitions. Unfortunately, a program built > > upon such a structure is neither reliable nor portable. > > It's both portable and reliable. It is portable because it causes the same kinds of problems wherever used. You can rely on this feature to be dangerous. For instance, an array of incomplete data types, or pointers to the same, will cause a violation of the rules you state above. That array can be created, but not manipulated. In C, all array element access involves pointer arithmetic. This is true even when using array indexing directly. The compiler simply substitutes pointer arithmetic for the indexing notation. > > > Ada does not allow you to compile a program with an incomplete type > > definition. There is no equivalent because the existence of an > > equivalent to this C capability would only introduce errors in your > > program. There is nothing positive that can be achieved by allowing > > a program to be incompletely specified. > > Sure, if your favourite language has no feature X, > then feature X is useless. Ada does not have this feature because its danger was judged to outweigh its value. That does not make this feature useless. It only makes it unsafe. > Incomplete types warrant opacity. This is important in C because of its lack of private data types. More modern languages achieve opacity without sacrificing program safety. Jim Rogers Colorado Springs, Colorado USA ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: type Foo_ptr in new void*; 2001-07-31 3:06 ` James Rogers @ 2001-07-31 5:02 ` Warren W. Gay VE3WWG 2001-07-31 7:22 ` Florian Weimer 1 sibling, 0 replies; 19+ messages in thread From: Warren W. Gay VE3WWG @ 2001-07-31 5:02 UTC (permalink / raw) James Rogers wrote: > Tomasz Wegrzanowski wrote: > > In article <3B64C26F.C195B4E0@worldnet.att.net>, James Rogers wrote: > > > Yes, you are correct. C does allow you to forward declare a structure > > > or a pointer without ever completing the definition. This is one of > > > the nasty capabilities "provided" by C. You can even create an array > > > of Foo *. However, pointer arithmetic from the start of this array > > > produces unspecified behavior. What is the sizeof Foo? Since it is > > > undefined, there is no correct answer to that question. Without a > > > proper definition of the sizeof Foo, there can be no reliable pointer > > > arithmetic. > > > > Correct answer is compilation error. > > It's illegal to do pointer arith on void* or incomplete types. Yes, that is correct (that it is illegal). > It is illegal, but not necessarily caught by the compiler. > This means that the correct answer is not compilation error. > C compilers are actually pretty primitive in their understanding of > data type completion. They rely on highly intelligent linkers to > find all the completions. Unfortunately, linker diagnostic messages Huh? What does linking have to do with pointer arithmetic and "incomplete types"? I remember some bad C compilers (Aztec C on the Mac comes to mind), but even the ever forgiving HP C compiler would catch this kind of stuff (incomplete type and pointer arithmetic that is). As far as allowing "undefined pointer arithmetic" without a compiler warning or error, you need to cite specific compiler brands, and show examples. Otherwise this is just rubbish, as far as I can see. I've only seen error messages when pointer arithmetic is required for incompletely defined types. > If you do not TRULY know the type of the data pointed to by a void*, > and then you cast it to some type, expecting correct results, you > will sometimes get a nasty surprise. Pointer arithmetic will be > performed, but your view of the data will be incorrect due to > poor alignment problems. Of course. If you cast _any_ pointer to another pointer type, you cannot expect the arithmetic to be necessarily the same! So what's the point? All C programmers know this already. You as the C programmer have said "I know what I'm doing and I want you the compiler to treat this address as a pointer to type Z, and by golly, you better do pointer arithmetic according to the Z type." After that, are you really surprised that the C compiler generates code that does arithmetic on the pointer by type Z? > Jim Rogers > Colorado Springs, Colorado USA C compilers (as with the C language), do have "issues". But not the one you've chosen here. -- Warren W. Gay VE3WWG http://members.home.net/ve3wwg ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: type Foo_ptr in new void*; 2001-07-31 3:06 ` James Rogers 2001-07-31 5:02 ` Warren W. Gay VE3WWG @ 2001-07-31 7:22 ` Florian Weimer 1 sibling, 0 replies; 19+ messages in thread From: Florian Weimer @ 2001-07-31 7:22 UTC (permalink / raw) James Rogers <jimmaureenrogers@worldnet.att.net> writes: >> It's illegal to do pointer arith on void* or incomplete types. > > It is illegal, but not necessarily caught by the compiler. C compilers must issue diagnostics if the source code contains pointer arithmetic on an incomplete type. > This means that the correct answer is not compilation error. It is, read the standard: there is a constraint that pointer arithmetic shall be done only on pointers to object types (which excludes function pointers and pointers to incomplete types), and constraint violations must be detected by the compiler. > C compilers are actually pretty primitive in their understanding of > data type completion. It's not that primitive. > They rely on highly intelligent linkers to find all the completions. The C object model certainly does not require any linker support for incomplete types. In fact, types never appear in linker input. (Of course, there are obscure targets for which these things are not true, e.g. the x86 target with a segmented memory model, but it's quite hard for compilers for such targets to conform to the C standard anyway). ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: type Foo_ptr in new void*; 2001-07-30 2:09 ` James Rogers 2001-07-30 2:36 ` Warren W. Gay VE3WWG 2001-07-31 1:21 ` Tomasz Wegrzanowski @ 2001-07-31 4:56 ` Darren New 2001-08-04 6:05 ` David Thompson 2 siblings, 1 reply; 19+ messages in thread From: Darren New @ 2001-07-31 4:56 UTC (permalink / raw) > You can even create an array > of Foo *. However, pointer arithmetic from the start of this array > produces unspecified behavior. Errrr, no it doesn't. > What is the sizeof Foo? Irrelevant, if you have an array of Foo*. If you have an array of Foo, it's relevant. > Since it is > undefined, there is no correct answer to that question. Without a > proper definition of the sizeof Foo, there can be no reliable pointer > arithmetic. Right. That's why you can't do pointer arithmetic on a Foo* without defining Foo. Which is not to say that Ada isn't superior to C in this respect. But what do you think a compiler is going to do if you index an array of Foo without defining Foo? Just randomly make up a sizeof(Foo) from whole cloth? There's probably something in the standard about this. -- Darren New / Senior MTS & Free Radical / Invisible Worlds Inc. San Diego, CA, USA (PST). Cryptokeys on demand. dnew@san.rr.com Only a WIMP puts wallpaper on his desktop. ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: type Foo_ptr in new void*; 2001-07-31 4:56 ` Darren New @ 2001-08-04 6:05 ` David Thompson 2001-08-05 2:27 ` Warren W. Gay VE3WWG 0 siblings, 1 reply; 19+ messages in thread From: David Thompson @ 2001-08-04 6:05 UTC (permalink / raw) Darren New <dnew@san.rr.com> wrote : ... > > Since [sizeof a C incomplete struct type namely Foo] is > > undefined, there is no correct answer to that question. Without a > > proper definition of the sizeof Foo, there can be no reliable pointer > > arithmetic. > > Right. That's why you can't do pointer arithmetic on a Foo* without > defining Foo. > One thing the previous poster might have been thinking of is that in C89/90 you could _declare_ as "extern" an array of an incomplete type; you might also be able to declare/define a function (formal) parameter as array of incomplete since that can be "adjusted" to a pointer, and pointer to incomplete is fine, although the WG response to Defect Report 047 held that this is not guaranteed; you could also define a typedef for array-of-incomplete if ultimately used only as above. You could _define_ (allocate) an actual array object only with a complete element type. Since you can't do pointer arithmetic (and thus []) on it, the only thing you could do with an array-of-incomplete was pass its address (pointer) to some other code which _does_ know about the completed type. In C99, this feature(?) is gone; it is now a constraint (6.7.5.2p1) on the array declarator that the element type must be complete in all cases, and thus a required diagnostic if not (see below). (But even when compilers start supporting C99, I expect some, maybe many, will still have options to get C89 behavior.) > Which is not to say that Ada isn't superior to C in this respect. > In particular, in C it is the programmer's responsibility to have different translation units (roughly, source files) use identical definitions (or nearly so) for a struct type. It is easy to get this wrong; the implementation is not required to detect it; and many, probably most, don't, since the compile+link model doesn't normally support it, although it would be legal. (I do know one implementation where the linker checks that function parameters which are pointers agree on the _size_ of the target; this doesn't catch all errors, but does help a good bit. I think it does so primarily because it needs this info in the object file for Fortran and COBOL, and C goes along for the ride.) Actually writing different definitions in two different sources is fairly obvious, but there are subtler ways to screw up. One is to change the definition in a .h file and recompile some but not all of the .c's that use it; tools like make help with this. Another is to have two same-named .h files in different directories/subtrees and select a wrong one. A third is to actually include the correct and same .h but it in turn uses #define's which are set differently (a coworker recently lost several days to that last; even a full de novo build doesn't catch or fix it). > But what do you think a compiler is going to do if you index an array of > Foo without defining Foo? Just randomly make up a sizeof(Foo) from whole > cloth? There's probably something in the standard about this. > If anyone really cares (from C99 = ANSI/ISO/IEC 9899:1999) - 6.5.2.1 defines subscripting (partly) in terms of pointer addition - 6.5.6p2 requires in a constraint that (one) operand of pointer addition be "to an object type" - 6.2.5p1 defines "object type" to exclude incomplete types. (Those places in the standard that want to allow incomplete types say "object or incomplete type".) - 6.5.3.4p1 requires in a constraint that sizeof "shall not be applied to ... an incomplete type ..." (sizeof is not actually used in the _definition_ of pointer arithmetic directly, although that's the usual implementation, only indirectly through 6.2.5p20 array elements are contiguous) - 5.1.1.3 requires "at least one diagnostic message" if there is "a violation of any syntax rule or constraint" -- although the standard doesn't require _useful_ diagnostics; it is only a nonnormative footnote that it _should_ "identify the nature of, and where possible localize, each violation." Having diagnosed a violation, the implementation is permitted to do anything whatsoever, even continue to translate and execute; this is Undefined Behavior "on which this International Standard imposes no requirements" (much like Ada Unbounded Error). If a compiler writer was silly enough to think that a random (more likely pseudorandom) sizeof here was a good idea, they could. More plausible is to just use whatever value happens to be in some slot of the symbol table that would be correct for a complete type but isn't valid (wasn't set) for incomplete. HAND. -- - David.Thompson 1 now at worldnet.att.net ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: type Foo_ptr in new void*; 2001-08-04 6:05 ` David Thompson @ 2001-08-05 2:27 ` Warren W. Gay VE3WWG 0 siblings, 0 replies; 19+ messages in thread From: Warren W. Gay VE3WWG @ 2001-08-05 2:27 UTC (permalink / raw) David Thompson wrote: > Darren New <dnew@san.rr.com> wrote : > ... > Actually writing different definitions in two different sources > is fairly obvious, but there are subtler ways to screw up. > One is to change the definition in a .h file and recompile > some but not all of the .c's that use it; tools like make > help with this. Another is to have two same-named .h files > in different directories/subtrees and select a wrong one. > A third is to actually include the correct and same .h > but it in turn uses #define's which are set differently > (a coworker recently lost several days to that last; > even a full de novo build doesn't catch or fix it). Another way to have this happen, is to have a "private" definition as the "proper type" which is used internally by the library, and an incorrect "opaque type" defined for public use. Or, this may have been correctly (but not portably) defined, but did not port correctly to the new platform. -- Warren W. Gay VE3WWG http://members.home.net/ve3wwg ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: type Foo_ptr in new void*; 2001-07-29 8:57 ` Tomasz Wegrzanowski 2001-07-29 12:26 ` Marc A. Criley @ 2001-07-29 13:40 ` Dale Stanbrough 1 sibling, 0 replies; 19+ messages in thread From: Dale Stanbrough @ 2001-07-29 13:40 UTC (permalink / raw) Tomasz Wegrzanowski wrote: > I can't do this. > Foo is supposed to be used only as a pointer. > I don't know if newer version of library will use the same Foo. One possibility is... subtype Foo is System.Address; (or just use System.Address). You could also declare a pointer to <anytype>, and use unchecked conversion back and forth to the pointer types that you want. Dale ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: type Foo_ptr in new void*; 2001-07-29 4:31 type Foo_ptr in new void*; Tomasz Wegrzanowski 2001-07-29 5:56 ` tmoran @ 2001-07-29 14:12 ` Florian Weimer 1 sibling, 0 replies; 19+ messages in thread From: Florian Weimer @ 2001-07-29 14:12 UTC (permalink / raw) taw@pb220.legnica.sdi.tpnet.pl (Tomasz Wegrzanowski) writes: > How should I typedef Foo* ? What is 'Foo'? 'void'? In this case, use the following, which is guaranteed to be portable: type Foo_ptr is new Interfaces.C.Strings.chars_ptr; ^ permalink raw reply [flat|nested] 19+ messages in thread
end of thread, other threads:[~2001-08-05 2:27 UTC | newest] Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2001-07-29 4:31 type Foo_ptr in new void*; Tomasz Wegrzanowski 2001-07-29 5:56 ` tmoran 2001-07-29 8:57 ` Tomasz Wegrzanowski 2001-07-29 12:26 ` Marc A. Criley 2001-07-30 1:05 ` Tomasz Wegrzanowski 2001-07-30 1:20 ` tmoran 2001-07-30 2:09 ` James Rogers 2001-07-30 2:36 ` Warren W. Gay VE3WWG 2001-07-30 3:10 ` James Rogers 2001-07-31 2:14 ` Warren W. Gay VE3WWG 2001-07-31 1:21 ` Tomasz Wegrzanowski 2001-07-31 3:06 ` James Rogers 2001-07-31 5:02 ` Warren W. Gay VE3WWG 2001-07-31 7:22 ` Florian Weimer 2001-07-31 4:56 ` Darren New 2001-08-04 6:05 ` David Thompson 2001-08-05 2:27 ` Warren W. Gay VE3WWG 2001-07-29 13:40 ` Dale Stanbrough 2001-07-29 14:12 ` Florian Weimer
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox