I was just thinking about the virtues of C vs. C++ wrt. ADT/generic
programming. The biggest complaint about writing container libraries for
ADTs is that void * offers no type safety. Does it really have to be this
way?
Couldn't you for instance track an object's accesses with void pointers and
ensure they are used consistently across calls?
---------
typedef struct {
size_t count;
/* ... */
void *data;
} array_t;
int array_push(array_t *array, void *data);
void *array_pop(array_t *array);
---------
Based on these two interface functions, we can on an individual object of
type array_t track that the parameter passed to push() has the same type as
the one to which you would assign from the pop() function.
Of course, for functions that take multiple void arguments or use void
arguments in inconsistent ways, we would need to track how those arguments
are used and are eventually assigned/read to/from the members of type
array_t.
This would appear to work in theory for code in which you have all the
source files available. It falls apart however when you only have a header
file as a specification for a pre-compiled library. I suppose since the
parameter identifiers are optional in function prototypes that you might be
able to divine something if the programmer elects to use some sort of
predictable naming for the void arguments.
At any rate, it was just a random thought. My idea is full of holes but it
was at least in the spirit of C :)
Thanks,
-Clint 19 1622
Clint Olsen <cl***@0lsen.net> wrote:
# I was just thinking about the virtues of C vs. C++ wrt. ADT/generic
# programming. The biggest complaint about writing container libraries for
# ADTs is that void * offers no type safety. Does it really have to be this
# way?
Then don't use C. There are other languages that are plenty
type safe. You can even write your front end to convert
a more sophisticated type checking language into C, or hire
people like me to write a front end for you.
--
SM Ryan http://www.rawbw.com/~wyrmwif/
JUSTICE!
Justice is dead.
Clint Olsen wrote: I was just thinking about the virtues of C vs. C++ wrt. ADT/generic programming. The biggest complaint about writing container libraries for ADTs is that void * offers no type safety. Does it really have to be this way?
Its not just void *, but <anything> * that has little to no type
safety. That's C's *real* problem w.r.t. safety. If you want to avoid
void *, its not a problem, but avoiding pointers in general -- you
won't get too far in C trying that.
Couldn't you for instance track an object's accesses with void pointers and ensure they are used consistently across calls?
---------
typedef struct { size_t count; /* ... */ void *data; } array_t;
int array_push(array_t *array, void *data); void *array_pop(array_t *array);
---------
Well actually the way to do this is as follows:
struct tagarray {
size_t count;
/* ... */
void * data;
};
extern int untyped_array_push (struct tagarray *array, void *data);
extern void *untyped_array_pop (struct tagarray *array);
Then you write the following wrappers:
struct <name>_tagarrwrap {
struct tagarray generic;
}
int <name>_array_push (struct <name>_tagarrwrap *array, <type> * data)
{
return untyped_array_push (&array->generic, (void *) data);
}
<type> * <name>_array_pop (struct <name>_tagarrwrap *array) {
return (<type> *) untyped_array_pop (&array->generic);
}
The point is that these wrappers are so syntactically trivial, that you
can invoke them as a result of some (name, type) indexed macro. Then
you just use these wrapper functions.
Now if C were any good of a language, this would be *perfect*. You
could even hide the struct tagarray definition inside a generic module
(its definition is unnecessary except for the generic void * function
implementations), this would be about as safe as you get -- *EXCEPT* C
is so worthless ...
No matter what <type> you pick, you won't get any type safety. For
example, if we've set up an int array:
genericArrayImpl (foo, int); /* Let's say this is our macro */
struct foo_tagarrwrap arrInt;
float y = 2.0; /* This is not an int */
foo_array_push (arrInt, &y);
The compiler won't even give you a warning here. You don't actually
*have* anything resembling typesafety in C. You need to use a C++
compiler before you are informed of any kind of an error here.
So we've avoided void*, but we haven't actually gained any typesafety,
unless we require the use of a C++ compiler. But in that case, why not
simply use the C++ language capabilities to do this right via
templates?
--
Paul Hsieh http://www.pobox.com/~qed/ http://bstring.sf.net/
<snip> genericArrayImpl (foo, int); /* Let's say this is our macro */ struct foo_tagarrwrap arrInt; float y = 2.0; /* This is not an int */
foo_array_push (arrInt, &y);
The compiler won't even give you a warning here. You don't actually *have* anything resembling typesafety in C. You need to use a C++ compiler before you are informed of any kind of an error here.
Huh? It is illegal to implicitly convert from float* to int*, if that's what
you are hinting at. See sections 6.5.16.1 of the C99 spec, for example. The
OP posted that void* is the gateway to implicitly throwing away type safety
and he's right.
On 2006-02-22, we******@gmail.com <we******@gmail.com> wrote: So we've avoided void*, but we haven't actually gained any typesafety, unless we require the use of a C++ compiler. But in that case, why not simply use the C++ language capabilities to do this right via templates?
Thanks for your post.
The problem I have with C++ and other template-style programming is that
the functions are instantiated for every unique type they use. It sort of
reminds me of the old days of C++ that where it was primarily a language
front-end and just blurted out C. Yeah, it's type safe, but it seems like
we could make smarter compilers that used the _same_ exact code to do the
same work. I don't know enough about generic programming support in other
languages to compare C++ against, but it seems they are sort of doing an
end-around approach to get type safety. After all, it's just damn bytes
we're talking about in the end.
Thanks,
-Clint
On 22 Feb 2006 09:55:15 -0800, in comp.lang.c , we******@gmail.com
wrote: Clint Olsen wrote: I was just thinking about the virtues of C vs. C++ wrt. ADT/generic programming. The biggest complaint about writing container libraries for ADTs is that void * offers no type safety. Does it really have to be this way? Its not just void *, but <anything> * that has little to no type safety. That's C's *real* problem w.r.t. safety.
Well sure, C isn't particularly type safe. Since when is this news? If
you want C++ you know where to find it.
Now if C were any good of a language,
Here we go again.
No matter what <type> you pick, you won't get any type safety. For example, if we've set up an int array:
genericArrayImpl (foo, int); /* Let's say this is our macro */ struct foo_tagarrwrap arrInt; float y = 2.0; /* This is not an int */
foo_array_push (arrInt, &y);
The compiler won't even give you a warning here.
If you've avoided void*, then the compiler will warn you about the
above, since int* and float* are incompatible, as are float* and a
pointer-to-struct.
You don't actually know C that well do you?
Mark McIntyre
--
"Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are,
by definition, not smart enough to debug it."
--Brian Kernighan
----== Posted via Newsfeeds.Com - Unlimited-Unrestricted-Secure Usenet News==---- http://www.newsfeeds.com The #1 Newsgroup Service in the World! 120,000+ Newsgroups
----= East and West-Coast Server Farms - Total Privacy via Encryption =----
"Clint Olsen" <cl***@0lsen.net> wrote in message
news:sl******************@belle.0lsen.net... I was just thinking about the virtues of C vs. C++ wrt. ADT/generic programming. The biggest complaint about writing container libraries for ADTs is that void * offers no type safety. Does it really have to be this way?
Couldn't you for instance track an object's accesses with void pointers
and ensure they are used consistently across calls?
From the other posts, it sounds like you may need C to be completely safe.
There are a number of programs which will help you make your C programs much
safer, such as LINT, CCURED, or CIL. Or, you could switch to a different
language such as Lustre and then run SCADE which was used sucessfully with
EADS Airbus.
Rod Pemberton
Clint Olsen wrote: On 2006-02-22, we******@gmail.com <we******@gmail.com> wrote:
So we've avoided void*, but we haven't actually gained any typesafety, unless we require the use of a C++ compiler. But in that case, why not simply use the C++ language capabilities to do this right via templates?
Thanks for your post.
The problem I have with C++ and other template-style programming is that the functions are instantiated for every unique type they use. It sort of reminds me of the old days of C++ that where it was primarily a language front-end and just blurted out C. Yeah, it's type safe, but it seems like we could make smarter compilers that used the _same_ exact code to do the same work.
Well you can do this with a container like you describe by using void*
for the internals, with a template wrapper that imposes the type safety.
With care, the wrapper member functions are trivial and will be
inlined away.
You probably could simulate this is C with a struct comprising function
pointers defined within a macros, something like:
#define X( type ) \
typedef struct xX##type { \
void (*push)( array_t*, type ); \
} X##type; \
void push##type##( array_t* array, type data ) { \
array_push( array, (void*)data); }
#define GET_X( type, name ) \
X##type name; \
name.push = push##type;
X(int)
int main()
{
GET_X( int, x );
array_t array;
x.push( &array, 42 );
}
--
Ian Collins.
Ian Collins wrote: Clint Olsen wrote: On 2006-02-22, we******@gmail.com <we******@gmail.com> wrote:
So we've avoided void*, but we haven't actually gained any typesafety, unless we require the use of a C++ compiler. But in that case, why not simply use the C++ language capabilities to do this right via templates?
Thanks for your post.
The problem I have with C++ and other template-style programming is that the functions are instantiated for every unique type they use. It sort of reminds me of the old days of C++ that where it was primarily a language front-end and just blurted out C. Yeah, it's type safe, but it seems like we could make smarter compilers that used the _same_ exact code to do the same work.
Well you can do this with a container like you describe by using void* for the internals, with a template wrapper that imposes the type safety. With care, the wrapper member functions are trivial and will be inlined away.
You probably could simulate this is C with a struct comprising function pointers defined within a macros, something like:
#define X( type ) \ typedef struct xX##type { \ void (*push)( array_t*, type ); \ } X##type; \ void push##type##( array_t* array, type data ) { \ array_push( array, (void*)data); }
Well this means that the data is getting implicitely copied into from
the call site to the local parameter. The cast to (void *) looks
wrong, I think you mean: (void *)&data, but you're still getting 1
shallow copy (suppose <type> is a struct.)
#define GET_X( type, name ) \ X##type name; \ name.push = push##type;
I'm not sure what you're gaining from this function pointer abstraction
since you are requiring, specifically "push##type" to exist in file
scope.
I think my way works best in practice, *except* for the fact that when
you build many of them for various types, the lack of type safety so
easily leads to utter chaos. Unless you run it through a C++ compiler,
but then its just ironic.
--
Paul Hsieh http://www.pobox.com/~qed/ http://bstring.sf.net/ we******@gmail.com wrote: You probably could simulate this is C with a struct comprising function pointers defined within a macros, something like:
#define X( type ) \ typedef struct xX##type { \ void (*push)( array_t*, type ); \ } X##type; \ void push##type##( array_t* array, type data ) { \ array_push( array, (void*)data); }
Well this means that the data is getting implicitely copied into from the call site to the local parameter. The cast to (void *) looks wrong, I think you mean: (void *)&data, but you're still getting 1 shallow copy (suppose <type> is a struct.)
Actually, it should have been 'type* data )' in the function definition,
I was assuming type was a struct.#define GET_X( type, name ) \ X##type name; \ name.push = push##type;
I'm not sure what you're gaining from this function pointer abstraction since you are requiring, specifically "push##type" to exist in file scope.
The ability to create an instance of the object, as illustrated by the
example push in my original post.
I was specifically demonstrating how to mimic template in C with macros.
I think my way works best in practice, *except* for the fact that when you build many of them for various types, the lack of type safety so easily leads to utter chaos. Unless you run it through a C++ compiler, but then its just ironic.
That's why I added the function pointers, they are type safe.
--
Ian Collins.
Ian Collins wrote: we******@gmail.com wrote:You probably could simulate this is C with a struct comprising function pointers defined within a macros, something like:
#define X( type ) \ typedef struct xX##type { \ void (*push)( array_t*, type ); \ } X##type; \ void push##type##( array_t* array, type data ) { \ array_push( array, (void*)data); } Well this means that the data is getting implicitely copied into from the call site to the local parameter. The cast to (void *) looks wrong, I think you mean: (void *)&data, but you're still getting 1 shallow copy (suppose <type> is a struct.)
Actually, it should have been 'type* data )' in the function definition, I was assuming type was a struct.
Well, then x.push (array, <any pointer>) is not going to be properly
type checked. #define GET_X( type, name ) \ X##type name; \ name.push = push##type;
I'm not sure what you're gaining from this function pointer abstraction since you are requiring, specifically "push##type" to exist in file scope.
The ability to create an instance of the object, as illustrated by the example push in my original post.
I was specifically demonstrating how to mimic template in C with macros.
Well, you are also using function pointers. This is a performance
concession, especially if you allow it to have an external interface --
then the compiler can't be "smart", and you eat the indirect function
call cost. I think my way works best in practice, *except* for the fact that when you build many of them for various types, the lack of type safety so easily leads to utter chaos. Unless you run it through a C++ compiler, but then its just ironic.
That's why I added the function pointers, they are type safe.
Uhhm ... not on the C compilers I use. In fact, I encourage a related
function pointer abuse in Bstrlib (though, I don't require it -- you
can be to the letter if you want; and they are cases where no real
system is actually going to go wrong) for some cases, and it doesn't
come up as an issue.
From what I can tell, pointers are basically never checked by the
compilers -- they take the attitude that all pointers are the same (or
that the programmer knows what s/he's doing), and this includes
function pointer parameters. You have to actually dereference before
you get an error. Obviously you can't get away with this in C++.
I'll check this all again when I get access to a compiler again (I am
not near that kind of a system right now) but I'm pretty sure
contemporary modern C compilers all just screw you on this issue. (The
question is -- is this a "NULLStone" compliance issue, or what? -- Why
do *ALL* the C compilers screw you on this?)
--
Paul Hsieh http://www.pobox.com/~qed/ http://bstring.sf.net/ we******@gmail.com wrote: I'm not sure what you're gaining from this function pointer abstraction since you are requiring, specifically "push##type" to exist in file scope. The ability to create an instance of the object, as illustrated by the example push in my original post.
I was specifically demonstrating how to mimic template in C with macros.
Well, you are also using function pointers. This is a performance concession, especially if you allow it to have an external interface -- then the compiler can't be "smart", and you eat the indirect function call cost.
Agreed, that's one big hit when simulating templates over using C++
templates. C++ compiles will inline the trivial wrapper functions.I think my way works best in practice, *except* for the fact that when you build many of them for various types, the lack of type safety so easily leads to utter chaos. Unless you run it through a C++ compiler, but then its just ironic.
That's why I added the function pointers, they are type safe.
Uhhm ... not on the C compilers I use. In fact, I encourage a related function pointer abuse in Bstrlib (though, I don't require it -- you can be to the letter if you want; and they are cases where no real system is actually going to go wrong) for some cases, and it doesn't come up as an issue.
Yes it will complain, based on my earlier macros:
#define X( type ) \
typedef struct xX##type { \
void (*push)( array_t*, type ); \
} X##type; \
\
void push##type##( array_t* array, type data ) { \
array_push( array, data); }
#define GET_X( type, name ) \
X##type name; \
name.push = push##type;
typedef int* intp;
X(intp)
int main()
{
GET_X( intp, x );
array_t array;
int n = 0;
float f = 0.0;
x.push( &array, &n );
x.push( &array, &f );
}
Will generate warnings for x.push( &array, &f );
--
Ian Collins. we******@gmail.com writes:
[...] From what I can tell, pointers are basically never checked by the compilers -- they take the attitude that all pointers are the same (or that the programmer knows what s/he's doing), and this includes function pointer parameters. You have to actually dereference before you get an error. Obviously you can't get away with this in C++.
I'll check this all again when I get access to a compiler again (I am not near that kind of a system right now) but I'm pretty sure contemporary modern C compilers all just screw you on this issue. (The question is -- is this a "NULLStone" compliance issue, or what? -- Why do *ALL* the C compilers screw you on this?)
void foo(void)
{
int *ip;
float *fp;
ip = fp;
fp = ip;
}
% gcc -c tmp.c
tmp.c: In function `foo':
tmp.c:5: warning: assignment from incompatible pointer type
tmp.c:6: warning: assignment from incompatible pointer type
Show us an example that you think *ALL* C compilers screw you on.
--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Ian Collins wrote: we******@gmail.com wrote:I think my way works best in practice, *except* for the fact that when you build many of them for various types, the lack of type safety so easily leads to utter chaos. Unless you run it through a C++ compiler, but then its just ironic.
That's why I added the function pointers, they are type safe.
Uhhm ... not on the C compilers I use. In fact, I encourage a related function pointer abuse in Bstrlib (though, I don't require it -- you can be to the letter if you want; and they are cases where no real system is actually going to go wrong) for some cases, and it doesn't come up as an issue.
Yes it will complain, based on my earlier macros:
#define X( type ) \ typedef struct xX##type { \ void (*push)( array_t*, type ); \ } X##type; \ \ void push##type##( array_t* array, type data ) { \ array_push( array, data); }
#define GET_X( type, name ) \ X##type name; \ name.push = push##type;
typedef int* intp;
X(intp)
int main() { GET_X( intp, x );
array_t array; int n = 0; float f = 0.0; x.push( &array, &n ); x.push( &array, &f ); }
Will generate warnings for x.push( &array, &f );
Have you tried it? After adding in a return 0; MSVC 6.0 says there are
no problems at its highest warning level. I'll check it with Intel,
Watcom, Borland, and gcc in a couple days, but my recollection is that
only Intel at its very highest warning level says anything -- but
Intel's highest warning level is annoying (it tells you strlen(s) +
strlen(t) is suspect because strlen could be overridden and have a side
effect and the + operation does not guarantee order) and I think a lot
of people dial it down at least one level from the highest, at which
point we lose this warning.
--
Paul Hsieh http://www.pobox.com/~qed/ http://bstring.sf.net/ we******@gmail.com writes: Ian Collins wrote:
[...] Yes it will complain, based on my earlier macros:
#define X( type ) \ typedef struct xX##type { \ void (*push)( array_t*, type ); \ } X##type; \ \ void push##type##( array_t* array, type data ) { \ array_push( array, data); }
#define GET_X( type, name ) \ X##type name; \ name.push = push##type;
typedef int* intp;
X(intp)
int main() { GET_X( intp, x );
array_t array; int n = 0; float f = 0.0; x.push( &array, &n ); x.push( &array, &f ); }
Will generate warnings for x.push( &array, &f );
Have you tried it? After adding in a return 0; MSVC 6.0 says there are no problems at its highest warning level. I'll check it with Intel, Watcom, Borland, and gcc in a couple days, but my recollection is that only Intel at its very highest warning level says anything -- but Intel's highest warning level is annoying (it tells you strlen(s) + strlen(t) is suspect because strlen could be overridden and have a side effect and the + operation does not guarantee order) and I think a lot of people dial it down at least one level from the highest, at which point we lose this warning.
I'm surprised you got far enough to get any warnings. When I compiled
the above code with gcc, I got:
tmp.c:15: error: parse error before '*' token
tmp.c:15:1: pasting "pushintp" and "(" does not give a valid preprocessing token
tmp.c:15: error: parse error before '*' token
followed by a cascade of other errors.
Getting rid of the macros and stripping down the program, I tried
this:
void push_int(int *ptr)
{
/* ... */
}
int main(void)
{
struct {
void (*push)(int*);
} x;
x.push = push_int;
int n = 0;
float f = 0.0;
x.push( &n );
x.push( &f ); /* This is line 15 */
return 0;
}
"gcc -c tmp.c" gave me:
tmp.c: In function `main':
tmp.c:15: warning: passing arg 1 of pointer to function from incompatible pointer type
(This was without any arguments to increase the warning level.)
If you're using a compiler that doesn't at least warn you about this
kind of type mismatch, get a better compiler.
--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this. we******@gmail.com wrote: Will generate warnings for x.push( &array, &f );
Have you tried it? After adding in a return 0; MSVC 6.0 says there are no problems at its highest warning level.
Well it should. That's a rather old and non-compliant compiler.
Sun cc (normal warnings) gives:
"/tmp/x.c", line 28: warning: argument #2 is incompatible with prototype:
prototype: pointer to int : "unknown", line 0
argument : pointer to float
gcc (normal warnings) gives:
/tmp/x.c: In function `main':
/tmp/x.c:28: warning: passing arg 2 of pointer to function from
incompatible pointer type
--
Ian Collins.
Keith Thompson wrote:
I'm surprised you got far enough to get any warnings. When I compiled the above code with gcc, I got:
tmp.c:15: error: parse error before '*' token tmp.c:15:1: pasting "pushintp" and "(" does not give a valid preprocessing token tmp.c:15: error: parse error before '*' token
Interesting, gcc4 gives the error, gcc3 does not.
Which is correct and if it's gcc4, how does one use the preprocessor to
build a function prototype?
--
Ian Collins.
Ian Collins <ia******@hotmail.com> writes: Keith Thompson wrote: I'm surprised you got far enough to get any warnings. When I compiled the above code with gcc, I got: tmp.c:15: error: parse error before '*' token tmp.c:15:1: pasting "pushintp" and "(" does not give a valid preprocessing token tmp.c:15: error: parse error before '*' token Interesting, gcc4 gives the error, gcc3 does not.
Which is correct and if it's gcc4, how does one use the preprocessor to build a function prototype?
The first thing I'd do is drop the unnecessary ## operator that tried
to join an identifier to a '('. When I tried that with the posted
program, I got other errors that I didn't bother to track down.
To summarize: I don't know.
--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Keith Thompson wrote: Ian Collins <ia******@hotmail.com> writes:
Keith Thompson wrote:
I'm surprised you got far enough to get any warnings. When I compiled the above code with gcc, I got: tmp.c:15: error: parse error before '*' token tmp.c:15:1: pasting "pushintp" and "(" does not give a valid preprocessing token tmp.c:15: error: parse error before '*' token
Interesting, gcc4 gives the error, gcc3 does not.
Which is correct and if it's gcc4, how does one use the preprocessor to build a function prototype?
The first thing I'd do is drop the unnecessary ## operator that tried to join an identifier to a '('. When I tried that with the posted program, I got other errors that I didn't bother to track down.
You're right, removing the unnecessary ## fixes the error. It was
redundant anyway.
Adding
typedef int array_t;
extern int array_push(array_t *array, void *data);
to the top of the file as a kludge will remove any remaining errors.
--
Ian Collins.
Ian Collins wrote: Keith Thompson wrote: Ian Collins <ia******@hotmail.com> writes:Keith Thompson wrote: I'm surprised you got far enough to get any warnings. When I compiled the above code with gcc, I got: tmp.c:15: error: parse error before '*' token tmp.c:15:1: pasting "pushintp" and "(" does not give a valid preprocessing token tmp.c:15: error: parse error before '*' token
Interesting, gcc4 gives the error, gcc3 does not.
Which is correct and if it's gcc4, how does one use the preprocessor to build a function prototype?
The first thing I'd do is drop the unnecessary ## operator that tried to join an identifier to a '('. When I tried that with the posted program, I got other errors that I didn't bother to track down.
You're right, removing the unnecessary ## fixes the error. It was redundant anyway.
Adding
typedef int array_t; extern int array_push(array_t *array, void *data);
to the top of the file as a kludge will remove any remaining errors.
I have implemented the whole shehbang here: http://www.pobox.com/~qed/gstack.zip
The ## rules are annoying, and I find that in general, the way to deal
with them is to wrap that whole thing in a two-level macro itself (it
works, so long as we don't care about namespace invasion).
--
Paul Hsieh http://www.pobox.com/~qed/ http://bstring.sf.net/ This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics
by: Robert Brown |
last post by:
suppose I have the following table:
CREATE TABLE (int level, color varchar, length int, width int, height
int)
It has the following rows
1, "RED", 8, 10, 12
2, NULL, NULL, NULL, 20...
|
by: johny smith |
last post by:
I have never really understood the purpose of the void*.
I guess it is so different data types could for instance be passed into a
function. And then the function will re cast it to the correct...
|
by: john smith |
last post by:
I have never really understood the difference between the two notations
below.
I often run into code where they are passing in the address of some
location.
Some people do something like...
|
by: yezi |
last post by:
Hi, all:
I want to record some memory pointer returned from malloc, is possible
the code like below?
int memo_index;
int i,j;
char *tmp;
for (i=0;i<10;i++){
|
by: robinsand |
last post by:
Header File: car.h #if !defined CAR_H
#define CAR_H
enum TCarType { ctEconomy = 1, ctCompact, ctStandard, ctFullSize,
ctMiniVan, ctSUV };
class Car
{
public:
Car();
|
by: SRR |
last post by:
Why is it discouraged to explicitly typecast the void pointer returned
by malloc(); function?
For example:
{
int *p;
p = (int*)malloc(2*sizeof(int)); /*Explicit casting is done, therfore
it...
|
by: jason.cipriani |
last post by:
All right, I'm in this weird situation that's hard to explain but I've
put together a small example program that represents it. Please bear
with the fact that some of the stuff in the example seems...
|
by: Litvinov Sergey |
last post by:
My problem is the following one.
I have a huge number of objects of base class:
class Base {
public:
virtual void
method();
}
And a derived class:
|
by: raphfrk |
last post by:
Is this valid?
int a;
void *b;
b = (void *)a; // b points to a
b += 5*sizeof(*a); // b points to a
a = 100;
|
by: aa123db |
last post by:
Variable and constants
Use var or let for variables and const fror constants.
Var foo ='bar';
Let foo ='bar';const baz ='bar';
Functions
function $name$ ($parameters$) {
}
...
|
by: ryjfgjl |
last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
|
by: ryjfgjl |
last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
|
by: emmanuelkatto |
last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud.
Please let me know.
Thanks!
Emmanuel
|
by: BarryA |
last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
|
by: nemocccc |
last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
|
by: Hystou |
last post by:
There are some requirements for setting up RAID:
1. The motherboard and BIOS support RAID configuration.
2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
|
by: Oralloy |
last post by:
Hello folks,
I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>".
The problem is that using the GNU compilers,...
|
by: jinu1996 |
last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
| |