Is it possible to make void * safer? | Bytes (2024)

Clint Olsen

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(arra y_t *array, void *data);
void *array_pop(arra y_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

Feb 22 '06

Subscribe Reply

19 Is it possible to make void * safer? | Bytes (1) 1642 Is it possible to make void * safer? | Bytes (2)

  • <
  • 1
  • 2

websnarf

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/

Feb 23 '06 #11

Ian Collins

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.

Feb 23 '06 #12

Keith Thompson

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_Keit h) 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.

Feb 23 '06 #13

websnarf

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/

Feb 23 '06 #14

Keith Thompson

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_Keit h) 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.

Feb 24 '06 #15

Ian Collins

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.

Feb 24 '06 #16

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.

Feb 24 '06 #17

Keith Thompson

Ian Collins <ia******@hotma il.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_Keit h) 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.

Feb 24 '06 #18

Ian Collins

Keith Thompson wrote:

Ian Collins <ia******@hotma il.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(arra y_t *array, void *data);

to the top of the file as a kludge will remove any remaining errors.

--
Ian Collins.

Feb 24 '06 #19

websnarf

Ian Collins wrote:

Keith Thompson wrote:
Ian Collins <ia******@hotma il.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(arra y_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/

Feb 27 '06 #20

  • <
  • 1
  • 2

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

22 3017

Difficult Query: is this possible in SQL?

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 3, NULL, 9, 82, 25

Microsoft SQL Server

5 1849

void* questions

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 data type? I have an example here that does not seem to work. I pass in an integer in one case and a float in another case. When I pass the...

C / C++

4 3371

void* versus uint32*

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 this: foo( void* p_data ) // pass in a pointer to some data

C / C++

48 2136

is possible to build some pointer array?

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++){

C / C++

4 2015

How do I add exception-handling to this code and make sure it compiles and runs properly?

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();

C / C++

41 4925

Casting of void pointer returned by malloc()

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 is said to be a bad practice*/ /*Some codes*/ }

C / C++

9 2046

Is this void* cast safe?

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 useless, it's from a much more complex situation. The example program is confusing for me to think about and to look at, and even though I'm...

C / C++

11 1612

How make polymorphism optional?

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:

C / C++

160 5526

Question about void pointers

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;

C / C++

7541

Changing the language in Windows 10

by: Hystou |last post by:

Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language...

Windows Server

7821

Problem With Comparison Operator <=> in G++

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, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. ...

C / C++

8057

Maximizing Business Potential: The Nexus of Website Design and Digital Marketing

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 tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that...

Online Marketing

7900

Discussion: How does Zigbee compare with other wireless protocols in smart home applications?

by: tracyyun |last post by:

Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the...

General

6172

AI Job Threat for Devs

by: agi2029 |last post by:

Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then...

Career Advice

1 5452

Access Europe - Using VBA to create a class based on a table - Wed 1 May

by: isladogs |last post by:

The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes...

Microsoft Access / VBA

5169

Couldn’t get equations in html when convert word .docx file to html file in C#.

by: conductexam |last post by:

I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert...

C# / C Sharp

3571

Windows Forms - .Net 8.0

by: adsilva |last post by:

A Windows Forms form does not have the event Unload, like VB6. What one acts like?

Visual Basic .NET

1 1154

How to add payments to a PHP MySQL app.

by: muto222 |last post by:

How can i add a mobile payment intergratation into php mysql website.

PHP

Is it possible to make void * safer? | Bytes (2024)

References

Top Articles
21 Swiss Chard Recipes + Produce Guide
Declutter Recipes and Cookbooks to Meal Plan Better - Hello Brownlow
Chren, inaugural chair of the Department of Dermatology, to step down
The Shoppes At Zion Directory
Ess Compass Associate Portal Login
Subfinder Online
Osrs Tokkul Calculator
Spectrum Store Kansas City Photos
How To Find Someone's IP On Discord | Robots.net
Warren County Skyward
Badddae
Elanco Rebates.com 2022
Domains | Hosting | Email | Homepage Baukasten | WordPress
Pokemon Infinite Fusion Good Rod
Calculator Souo
Nccer Log In
Lorton Transfer Station
Synergy Grand Rapids Public Schools
How 'The Jordan Rules' inspired template for Raiders' 'Mahomes Rules'
Humongousbazonkers
Ar Kendrithyst
R/Chinatime
1v1 lol unblocked Game- Play Unblocked Game Online for Free!
How Much Is Cvs Sports Physical
The Perfect Couple Episode 5 Cast & Characters - Eve Hewson, Nicole Kidman & More (Photos)
Six Oaks Rv Park Mooresburg Tn
Solar Smash Secret Achievements List 2023
Elmira Star Gazette Obit
Kitchen Song Singer Violet Crossword
Meine Erfahrung mit Textbroker als Autor (inkl. Beispiel zu Verdienst)
New Orleans Magazine | Dining, Entertainment, Homes, Lifestyle and all things NOLA
Verde News Cottonwood Az
Bodek And Rhodes Catalog
Joy Jenkins Barnett Obituary
The Flash 2023 1080P Cam X264-Will1869
Panty Note Manga Online
New R-Link system and now issues creating R-Link store account.
Joe Bartlett Wor Salary
Jetnet Retirees Aa
Missing 2023 Showtimes Near Mjr Partridge Creek Digital Cinema 14
Ihop Ralph Ave
Makes A Successful Catch Maybe Crossword Clue
The Penitent One Unmasked
WHAT WE HAVE | Arizona Tile
Craigslist.com Hawaii
Epaper Dunya
Duxa.io Reviews
Knock At The Cabin Showtimes Near Alamo Drafthouse Raleigh
Love & Basketball streaming: where to watch online?
new hampshire real estate - craigslist
LP Vinyl Samling pop rock thrash metal trance
Enchiladas Suizas | Mexican Food Recipes, Quick and Easy.
Latest Posts
Article information

Author: Melvina Ondricka

Last Updated:

Views: 6466

Rating: 4.8 / 5 (68 voted)

Reviews: 83% of readers found this page helpful

Author information

Name: Melvina Ondricka

Birthday: 2000-12-23

Address: Suite 382 139 Shaniqua Locks, Paulaborough, UT 90498

Phone: +636383657021

Job: Dynamic Government Specialist

Hobby: Kite flying, Watching movies, Knitting, Model building, Reading, Wood carving, Paintball

Introduction: My name is Melvina Ondricka, I am a helpful, fancy, friendly, innocent, outstanding, courageous, thoughtful person who loves writing and wants to share my knowledge and understanding with you.