Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > inline function or macro?

Reply
Thread Tools

inline function or macro?

 
 
spinoza1111
Guest
Posts: n/a
 
      01-02-2010
On Jan 2, 5:41*pm, jacob navia <(E-Mail Removed)> wrote:
> One situation where macros are the only solution, and inline functions
> just do not cut it is when you have several structures that share a
> common field, and you want to access it without a function call.
>
> For instance in a container library (strange, what a coincidence )
> all the containers share the "count" field, that access the number of
> elements in the container.
>
> Here it would be impossible to use an inline function since all the
> containers are different types. A macro is the only solution:
>
> #define GetCount(container) (container->count)
>
> This will work with all containers. Unless you use lcc-win and have
> true generic functions (or use C++) the macro is the only really
> portable solution.


Yes, but that is why generics were added to .Net.

public static class containerTools<containerType>
{
public static int getCount(containerType container)
{
return container.count;
}
}

Simple, right?

There is a problem in your code. If container is an expression, the ->
may associate incorrectly. A well known fix that you probably know
would be to code

#define GetCount(container) ((container)->count)

unless I'm missing something.

Also, if container doesn't have a count, the emitted code won't
compile. I understand that this is true for macros in general. Either
the macro is well-documented, or you can see its code as in a white or
transparent box.

Lacking Turing-complete conditional assembly and a richer set of
functions which have long been available in languages such as
assembler, the macro is not able to validate its own parameters,
whereas I was able to do this in the macro language of IBM BAL. Even
if a C preprocessor could detect many errors, it has no way of
informing the user save a crude hack such as generating a printf()
that waits until runtime to say "you made an error"!

Now, a colleague whose name I won't mention in a probably futile
effort to make sure he stays away thinks that "macro processing" and
"conditional compilation" are two separate things: but in fact, when
you finish mere textual substitution, you're not done, since you
cannot error check parameters. This in fact was why almost as soon as
simple textual macros appeared in IBM assemblers of the 1950s, they
had to be enhanced with conditional compilation, the ability to emit
diagnostics and even crude loops that used macro-expansion-time Go Tos
to create loops. They were Turing-complete.

Have you considered, Mr Navia, replacing the C preprocessor with such
a macro processor, since you appear to be in the (too me rather
*maudit*) business of trying to make a sensible language out of C?

But: note that far more work is needed in C to get to the purse of
silk from the ear of sow or tongue of bat or eye of newt stage that it
appears to me C is stuck in.
 
Reply With Quote
 
 
 
 
Eric Sosman
Guest
Posts: n/a
 
      01-02-2010
On 1/2/2010 12:39 PM, jacob navia wrote:
> Eric Sosman a écrit :
>>
>> typedef struct {
>> size_t count;
>> nobili_t baron;
>> royal_t duke;
>> } AllContainersHaveThis;
>> [...]

>
> Sure, but then the access is
> container->common.count;
> and not
> container->count;
> what is easier on the user.


If you can do `container->count', why bother with
your `GetCount(container)' macro in the first place?
What problem are you trying to solve?

--
Eric Sosman
http://www.velocityreviews.com/forums/(E-Mail Removed)lid
 
Reply With Quote
 
 
 
 
jacob navia
Guest
Posts: n/a
 
      01-02-2010
Eric Sosman a écrit :
> On 1/2/2010 12:39 PM, jacob navia wrote:
>> Eric Sosman a écrit :
>>>
>>> typedef struct {
>>> size_t count;
>>> nobili_t baron;
>>> royal_t duke;
>>> } AllContainersHaveThis;
>>> [...]

>>
>> Sure, but then the access is
>> container->common.count;
>> and not
>> container->count;
>> what is easier on the user.

>
> If you can do `container->count', why bother with
> your `GetCount(container)' macro in the first place?
> What problem are you trying to solve?
>


I would prefer not to let users use "->count" directly in case
I need to change it later, because, for instance, capitalization
problems, (Count or count?), or because it is better to call
it NumberOfEelemnts, etc.

But not ALL members of the common subset have macros for them
since I want to avoid using common names as much as possible.

The GetCount macro is on by default, but if it collides with
one name in your name space you should be able to disable it.

As you know, C has no "hidden/protected" structure members.

 
Reply With Quote
 
Eric Sosman
Guest
Posts: n/a
 
      01-02-2010
On 1/2/2010 1:57 PM, jacob navia wrote:
> Eric Sosman a écrit :
>> On 1/2/2010 12:39 PM, jacob navia wrote:
>>> Eric Sosman a écrit :
>>>>
>>>> typedef struct {
>>>> size_t count;
>>>> nobili_t baron;
>>>> royal_t duke;
>>>> } AllContainersHaveThis;
>>>> [...]
>>>
>>> Sure, but then the access is
>>> container->common.count;
>>> and not
>>> container->count;
>>> what is easier on the user.

>>
>> If you can do `container->count', why bother with
>> your `GetCount(container)' macro in the first place?
>> What problem are you trying to solve?
>>

>
> I would prefer not to let users use "->count" directly in case
> I need to change it later, because, for instance, capitalization
> problems, (Count or count?), or because it is better to call
> it NumberOfEelemnts, etc.


If the users aren't supposed to access `count' directly,
why object that `container->count' is "easier on the user" than
`container->common.count'? Neither form will be used at all,
so why prefer one as "easier" than the other?

I still don't get it ...

> But not ALL members of the common subset have macros for them
> since I want to avoid using common names as much as possible.


Sorry: I don't understand this at all. I imagine this is
because I lack a good deal of context, design and implementation
details that reside in your head but not in mine.

> The GetCount macro is on by default, but if it collides with
> one name in your name space you should be able to disable it.


And thus give up the ability to find out how many elements
a container holds? I still *really* don't get it ...

> As you know, C has no "hidden/protected" structure members.


No. It's all or nothing: Expose all of a struct's elements,
or make the whole struct an incomplete type and hide everything.
(For an abstract data type like "container," the latter seems
such a natural choice that I don't understand why you avoid it.)

--
Eric Sosman
(E-Mail Removed)lid
 
Reply With Quote
 
Keith Thompson
Guest
Posts: n/a
 
      01-02-2010
jacob navia <(E-Mail Removed)> writes:
> One situation where macros are the only solution, and inline functions
> just do not cut it is when you have several structures that share a
> common field, and you want to access it without a function call.
>
> For instance in a container library (strange, what a coincidence )
> all the containers share the "count" field, that access the number of
> elements in the container.
>
> Here it would be impossible to use an inline function since all the
> containers are different types. A macro is the only solution:
>
> #define GetCount(container) (container->count)
>
> This will work with all containers. Unless you use lcc-win and have
> true generic functions (or use C++) the macro is the only really
> portable solution.


Judicious use of void* can let you use functions (inline or not),
though at some loss of type checking. The following sample code,
which expands on what Eric Sosman pointed, is a bit long; the GetCount
function is the relevant part.

#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>

typedef struct {
size_t count;
} AllContainersHaveThis;

typedef struct {
AllContainersHaveThis common;
int One;
} ContainerOne;

typedef struct {
AllContainersHaveThis common;
char *Two;
} ContainerTwo;

typedef struct {
AllContainersHaveThis common;
double Three;
} ContainerThree;

ContainerOne *new1(size_t count, int One)
{
ContainerOne *const result = malloc(sizeof *result);
if (result != NULL) {
result->common.count = count;
result->One = One;
}
return result;
}

ContainerTwo *new2(size_t count, char *Two)
{
ContainerTwo *const result = malloc(sizeof *result);
if (result != NULL) {
result->common.count = count;
result->Two = Two;
}
return result;
}

ContainerThree *new3(size_t count, double Three)
{
ContainerThree *const result = malloc(sizeof *result);
if (result != NULL) {
result->common.count = count;
result->Three = Three;
}
return result;
}

size_t GetCount(void *container)
{
const AllContainersHaveThis *common_ptr = container;
return common_ptr->count;
}

int main(void)
{
ContainerOne *c1 = new1(10, 42);
ContainerTwo *c2 = new2(20, "hello");
ContainerThree *c3 = new3(30, 1.375);
printf("GetCount(c1) = %zu\n", GetCount(c1));
printf("GetCount(c2) = %zu\n", GetCount(c2));
printf("GetCount(c3) = %zu\n", GetCount(c3));
return 0;
}

--
Keith Thompson (The_Other_Keith) (E-Mail Removed) <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
 
Reply With Quote
 
Keith Thompson
Guest
Posts: n/a
 
      01-02-2010
Keith Thompson <(E-Mail Removed)> writes:
> jacob navia <(E-Mail Removed)> writes:
>> One situation where macros are the only solution, and inline functions
>> just do not cut it is when you have several structures that share a
>> common field, and you want to access it without a function call.
>>
>> For instance in a container library (strange, what a coincidence )
>> all the containers share the "count" field, that access the number of
>> elements in the container.
>>
>> Here it would be impossible to use an inline function since all the
>> containers are different types. A macro is the only solution:
>>
>> #define GetCount(container) (container->count)
>>
>> This will work with all containers. Unless you use lcc-win and have
>> true generic functions (or use C++) the macro is the only really
>> portable solution.

>
> Judicious use of void* can let you use functions (inline or not),
> though at some loss of type checking. The following sample code,
> which expands on what Eric Sosman pointed, is a bit long; the GetCount
> function is the relevant part.

[snip]
> size_t GetCount(void *container)
> {
> const AllContainersHaveThis *common_ptr = container;
> return common_ptr->count;
> }

[snip]

A major drawback of this approach is that the compiler won't
complain about a call like
GetCount("hello");
(On my system it returned 1819043176, which is meaningful but not
in any useful way.)

--
Keith Thompson (The_Other_Keith) (E-Mail Removed) <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
 
Reply With Quote
 
Flash Gordon
Guest
Posts: n/a
 
      01-03-2010
Eric Sosman wrote:
> On 1/2/2010 1:57 PM, jacob navia wrote:
>> Eric Sosman a écrit :
>>> On 1/2/2010 12:39 PM, jacob navia wrote:
>>>> Eric Sosman a écrit :
>>>>>
>>>>> typedef struct {
>>>>> size_t count;
>>>>> nobili_t baron;
>>>>> royal_t duke;
>>>>> } AllContainersHaveThis;
>>>>> [...]
>>>>
>>>> Sure, but then the access is
>>>> container->common.count;
>>>> and not
>>>> container->count;
>>>> what is easier on the user.
>>>
>>> If you can do `container->count', why bother with
>>> your `GetCount(container)' macro in the first place?
>>> What problem are you trying to solve?
>>>

>>
>> I would prefer not to let users use "->count" directly in case
>> I need to change it later, because, for instance, capitalization
>> problems, (Count or count?), or because it is better to call
>> it NumberOfEelemnts, etc.


If you might decide to change it's name, then might you not also decide
to change GetCount to GetNumberOfElements? Or change its capitalization?
The only solution to the problem of what to call things and possibly
needing to rename them is to design everything sufficiently that the
odds are the name will always be appropriate and not clash with anything
else you might want to do.

> If the users aren't supposed to access `count' directly,
> why object that `container->count' is "easier on the user" than
> `container->common.count'? Neither form will be used at all,
> so why prefer one as "easier" than the other?
>
> I still don't get it ...
>
>> But not ALL members of the common subset have macros for them
>> since I want to avoid using common names as much as possible.

>
> Sorry: I don't understand this at all. I imagine this is
> because I lack a good deal of context, design and implementation
> details that reside in your head but not in mine.


It does seem odd to me. The one reason I can see you might want to do
some things wrapped in a macro or inline function is if count *might* be
a simple field or you *might* be calling a function which actually
counts the elements, but in that case make it a function with the simple
case just being a simple inline function.

>> The GetCount macro is on by default, but if it collides with
>> one name in your name space you should be able to disable it.

>
> And thus give up the ability to find out how many elements
> a container holds? I still *really* don't get it ...


Well, you could still access container->count ...
The macros/functions should have an appropriate prefix to minimise the
chances of a name clash. E.g. start everything with cnt (or Cnt) or
whatever. After all, you might be using another library which has a
GetCount function (which is, I think, Jacob's concern here).

>> As you know, C has no "hidden/protected" structure members.

>
> No. It's all or nothing: Expose all of a struct's elements,
> or make the whole struct an incomplete type and hide everything.
> (For an abstract data type like "container," the latter seems
> such a natural choice that I don't understand why you avoid it.)


It would be nice if you could have a struct which contains an incomplete
struct. Which, of course, would make it incomplete but still allow
access to some things...

struct container {
size_t count;
struct hidden hidden;
}

If this was added to C the container struct would obviously have most of
the same restrictions as any other incomplete type, i.e. you could
declare pointers to the type, not arrays or objects. You would need a
special case rule that you could dereference it if and *only* if you
then just accessed a member the definition of which you could see. Also
the incomplete type would have to be at the end (just as with flexible
array members).

I suppose you could just do an array which was large enough for all the
extra info you wanted then cast to/from the correct
pointer-to-struct-type inside the library.
--
Flash Gordon
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
How to know the inline-function was implemented the inline way or normal way? ypjofficial@indiatimes.com C++ 7 07-18-2006 11:22 PM
forcing compiler to consider inline function inline. Ajay C++ 5 04-01-2006 02:03 PM
Use of inline function in inline function - is it allowed? TGOS C Programming 3 02-28-2005 10:49 AM
Function delcared inline but not defined inline Nish C Programming 4 10-08-2004 03:31 PM
inline or not to inline in C++ Abhi C++ 2 07-03-2003 12:07 AM



Advertisments