C print a generic type vector











up vote
2
down vote

favorite












Hi I'm trying to create a function that takes a void* pointer as parameter and print all element of the vector using printf



the declaration of the function is:



void print_vec(void *vec,int dime_se,int dime,char *format);


and implementation is:



void print_vec(void *vec,int dime_se,int dime,char *format){
for(int i=0;i<dime;i++)
printf(format,*(vec+dime_se*i));
}


the problem is that when i compile the compiler returns:



error: invalid use of void expression printf(format,*(vec+dime_se*i));


So the question there is a way to do this task without make this?



void print_vec(void *vec,int dime_se,int dime,char *format){
for(int i=0;i<dime;i++)
switch(format[1]){
case 'c':
printf(format,*((char*)(vec+dime_se*i)));
break;

case 'd':
printf(format,*((unsigned int*)(vec+dime_se*i)));
break;


case 's':
printf(format,*((char**)(vec+dime_se*i)));
break;

case 'i':
printf(format,*((int*)(vec+dime_se*i)));
break;



case 'f':
printf(format,*((float*)(vec+dime_se*i)));
break;

default:
break;
}


}










share|improve this question


















  • 1




    no. C have not generic types. to call printfwith valid arguments compiler need extra information about size of arguments. in your example you use int, char, float and char* and they can have any size depends on your machine
    – kerrytazi
    yesterday








  • 1




    Pointer math on void* is not portable. (unsigned int*)(vec+dime_se*i) --> ((unsigned int*)vec + i)
    – chux
    yesterday






  • 1




    Why use 'd' with unsigned? 'd' goes with int. 'u' goes with unsigned.
    – chux
    yesterday















up vote
2
down vote

favorite












Hi I'm trying to create a function that takes a void* pointer as parameter and print all element of the vector using printf



the declaration of the function is:



void print_vec(void *vec,int dime_se,int dime,char *format);


and implementation is:



void print_vec(void *vec,int dime_se,int dime,char *format){
for(int i=0;i<dime;i++)
printf(format,*(vec+dime_se*i));
}


the problem is that when i compile the compiler returns:



error: invalid use of void expression printf(format,*(vec+dime_se*i));


So the question there is a way to do this task without make this?



void print_vec(void *vec,int dime_se,int dime,char *format){
for(int i=0;i<dime;i++)
switch(format[1]){
case 'c':
printf(format,*((char*)(vec+dime_se*i)));
break;

case 'd':
printf(format,*((unsigned int*)(vec+dime_se*i)));
break;


case 's':
printf(format,*((char**)(vec+dime_se*i)));
break;

case 'i':
printf(format,*((int*)(vec+dime_se*i)));
break;



case 'f':
printf(format,*((float*)(vec+dime_se*i)));
break;

default:
break;
}


}










share|improve this question


















  • 1




    no. C have not generic types. to call printfwith valid arguments compiler need extra information about size of arguments. in your example you use int, char, float and char* and they can have any size depends on your machine
    – kerrytazi
    yesterday








  • 1




    Pointer math on void* is not portable. (unsigned int*)(vec+dime_se*i) --> ((unsigned int*)vec + i)
    – chux
    yesterday






  • 1




    Why use 'd' with unsigned? 'd' goes with int. 'u' goes with unsigned.
    – chux
    yesterday













up vote
2
down vote

favorite









up vote
2
down vote

favorite











Hi I'm trying to create a function that takes a void* pointer as parameter and print all element of the vector using printf



the declaration of the function is:



void print_vec(void *vec,int dime_se,int dime,char *format);


and implementation is:



void print_vec(void *vec,int dime_se,int dime,char *format){
for(int i=0;i<dime;i++)
printf(format,*(vec+dime_se*i));
}


the problem is that when i compile the compiler returns:



error: invalid use of void expression printf(format,*(vec+dime_se*i));


So the question there is a way to do this task without make this?



void print_vec(void *vec,int dime_se,int dime,char *format){
for(int i=0;i<dime;i++)
switch(format[1]){
case 'c':
printf(format,*((char*)(vec+dime_se*i)));
break;

case 'd':
printf(format,*((unsigned int*)(vec+dime_se*i)));
break;


case 's':
printf(format,*((char**)(vec+dime_se*i)));
break;

case 'i':
printf(format,*((int*)(vec+dime_se*i)));
break;



case 'f':
printf(format,*((float*)(vec+dime_se*i)));
break;

default:
break;
}


}










share|improve this question













Hi I'm trying to create a function that takes a void* pointer as parameter and print all element of the vector using printf



the declaration of the function is:



void print_vec(void *vec,int dime_se,int dime,char *format);


and implementation is:



void print_vec(void *vec,int dime_se,int dime,char *format){
for(int i=0;i<dime;i++)
printf(format,*(vec+dime_se*i));
}


the problem is that when i compile the compiler returns:



error: invalid use of void expression printf(format,*(vec+dime_se*i));


So the question there is a way to do this task without make this?



void print_vec(void *vec,int dime_se,int dime,char *format){
for(int i=0;i<dime;i++)
switch(format[1]){
case 'c':
printf(format,*((char*)(vec+dime_se*i)));
break;

case 'd':
printf(format,*((unsigned int*)(vec+dime_se*i)));
break;


case 's':
printf(format,*((char**)(vec+dime_se*i)));
break;

case 'i':
printf(format,*((int*)(vec+dime_se*i)));
break;



case 'f':
printf(format,*((float*)(vec+dime_se*i)));
break;

default:
break;
}


}







c vector printf






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked yesterday









P.Carlino

394114




394114








  • 1




    no. C have not generic types. to call printfwith valid arguments compiler need extra information about size of arguments. in your example you use int, char, float and char* and they can have any size depends on your machine
    – kerrytazi
    yesterday








  • 1




    Pointer math on void* is not portable. (unsigned int*)(vec+dime_se*i) --> ((unsigned int*)vec + i)
    – chux
    yesterday






  • 1




    Why use 'd' with unsigned? 'd' goes with int. 'u' goes with unsigned.
    – chux
    yesterday














  • 1




    no. C have not generic types. to call printfwith valid arguments compiler need extra information about size of arguments. in your example you use int, char, float and char* and they can have any size depends on your machine
    – kerrytazi
    yesterday








  • 1




    Pointer math on void* is not portable. (unsigned int*)(vec+dime_se*i) --> ((unsigned int*)vec + i)
    – chux
    yesterday






  • 1




    Why use 'd' with unsigned? 'd' goes with int. 'u' goes with unsigned.
    – chux
    yesterday








1




1




no. C have not generic types. to call printfwith valid arguments compiler need extra information about size of arguments. in your example you use int, char, float and char* and they can have any size depends on your machine
– kerrytazi
yesterday






no. C have not generic types. to call printfwith valid arguments compiler need extra information about size of arguments. in your example you use int, char, float and char* and they can have any size depends on your machine
– kerrytazi
yesterday






1




1




Pointer math on void* is not portable. (unsigned int*)(vec+dime_se*i) --> ((unsigned int*)vec + i)
– chux
yesterday




Pointer math on void* is not portable. (unsigned int*)(vec+dime_se*i) --> ((unsigned int*)vec + i)
– chux
yesterday




1




1




Why use 'd' with unsigned? 'd' goes with int. 'u' goes with unsigned.
– chux
yesterday




Why use 'd' with unsigned? 'd' goes with int. 'u' goes with unsigned.
– chux
yesterday












1 Answer
1






active

oldest

votes

















up vote
4
down vote



accepted










You don't need the dime_se param. The size is more or less implicit in the format character.
Also, if you cast to the right pointer type you can let C do the scaling instead of doing it
manually:



#include <stddef.h>
#include <stdio.h>
void print_vec(void const*vec,size_t dime,char const*format)
{
for(size_t i=0;i<dime;i++)
switch(format[1]){
#define X(Char,Tp) break;case Char: printf(format,((Tp*)vec)[i])
X('c',char);
X('d',unsigned);
X('s',char*);
X('i',int);
X('f',float);
break;default: return;
#undef X
}
}


I said more or less because type promotion kind of blurs the line. %f could well mean you've got a double instead of a float.



If you want to use a dime_se parameter to disambiguate that case, you can:



         break;case 'f': 
if(sizeof(double)==dime_se)
printf(format,((double*)vec)[i]);
else {
assert(sizeof(float)==dime_se);
printf(format,((float*)vec)[i]);
}


but I'm not sure if a print_vec function like that is a good idea.






share|improve this answer























  • Note this answer will only work if your format string always start with a simple type like %d. If you want the function to do fancier printing like fixed number of decimals "%.02f", or print an entire message for each item in the vector, you would need a more complex parsing logic to rely on the format string for typing.
    – Lev M.
    yesterday






  • 1




    @chux Missed that. Thanks.
    – PSkocik
    yesterday










  • As coded, printing any 'f' returns right after printing (drop through) . Curious: why #define X(Char,Tp) break;case Char: printf(format,((Tp*)vec)[i]) and not #define X(Char,Tp) case Char: printf(format,((Tp*)vec)[i]); break ?
    – chux
    yesterday












  • @chux It's just how I write my switches if they contain mostly "breaking-cases". It doesn't matter with the macro, but in normal C code, if I see each case preceded by break; it'll make one that isn't stand out more easily than if the break were at the end of what follows the case. It helps me quickly catch accidental fall-through. I think it's pretty neat that the C grammar allows me to symmetrically start even the first case with break even though the break part is basically dead code there.
    – PSkocik
    yesterday










  • Hmmm, If you value break at the beginning, perhaps then #define X(Char,Tp) break;case Char: printf(format,((Tp*)vec)[i]); break to avoid the earlier coding oops that caused a "accidental fall-through".
    – chux
    yesterday













Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














 

draft saved


draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53237886%2fc-print-a-generic-type-vector%23new-answer', 'question_page');
}
);

Post as a guest
































1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes








up vote
4
down vote



accepted










You don't need the dime_se param. The size is more or less implicit in the format character.
Also, if you cast to the right pointer type you can let C do the scaling instead of doing it
manually:



#include <stddef.h>
#include <stdio.h>
void print_vec(void const*vec,size_t dime,char const*format)
{
for(size_t i=0;i<dime;i++)
switch(format[1]){
#define X(Char,Tp) break;case Char: printf(format,((Tp*)vec)[i])
X('c',char);
X('d',unsigned);
X('s',char*);
X('i',int);
X('f',float);
break;default: return;
#undef X
}
}


I said more or less because type promotion kind of blurs the line. %f could well mean you've got a double instead of a float.



If you want to use a dime_se parameter to disambiguate that case, you can:



         break;case 'f': 
if(sizeof(double)==dime_se)
printf(format,((double*)vec)[i]);
else {
assert(sizeof(float)==dime_se);
printf(format,((float*)vec)[i]);
}


but I'm not sure if a print_vec function like that is a good idea.






share|improve this answer























  • Note this answer will only work if your format string always start with a simple type like %d. If you want the function to do fancier printing like fixed number of decimals "%.02f", or print an entire message for each item in the vector, you would need a more complex parsing logic to rely on the format string for typing.
    – Lev M.
    yesterday






  • 1




    @chux Missed that. Thanks.
    – PSkocik
    yesterday










  • As coded, printing any 'f' returns right after printing (drop through) . Curious: why #define X(Char,Tp) break;case Char: printf(format,((Tp*)vec)[i]) and not #define X(Char,Tp) case Char: printf(format,((Tp*)vec)[i]); break ?
    – chux
    yesterday












  • @chux It's just how I write my switches if they contain mostly "breaking-cases". It doesn't matter with the macro, but in normal C code, if I see each case preceded by break; it'll make one that isn't stand out more easily than if the break were at the end of what follows the case. It helps me quickly catch accidental fall-through. I think it's pretty neat that the C grammar allows me to symmetrically start even the first case with break even though the break part is basically dead code there.
    – PSkocik
    yesterday










  • Hmmm, If you value break at the beginning, perhaps then #define X(Char,Tp) break;case Char: printf(format,((Tp*)vec)[i]); break to avoid the earlier coding oops that caused a "accidental fall-through".
    – chux
    yesterday

















up vote
4
down vote



accepted










You don't need the dime_se param. The size is more or less implicit in the format character.
Also, if you cast to the right pointer type you can let C do the scaling instead of doing it
manually:



#include <stddef.h>
#include <stdio.h>
void print_vec(void const*vec,size_t dime,char const*format)
{
for(size_t i=0;i<dime;i++)
switch(format[1]){
#define X(Char,Tp) break;case Char: printf(format,((Tp*)vec)[i])
X('c',char);
X('d',unsigned);
X('s',char*);
X('i',int);
X('f',float);
break;default: return;
#undef X
}
}


I said more or less because type promotion kind of blurs the line. %f could well mean you've got a double instead of a float.



If you want to use a dime_se parameter to disambiguate that case, you can:



         break;case 'f': 
if(sizeof(double)==dime_se)
printf(format,((double*)vec)[i]);
else {
assert(sizeof(float)==dime_se);
printf(format,((float*)vec)[i]);
}


but I'm not sure if a print_vec function like that is a good idea.






share|improve this answer























  • Note this answer will only work if your format string always start with a simple type like %d. If you want the function to do fancier printing like fixed number of decimals "%.02f", or print an entire message for each item in the vector, you would need a more complex parsing logic to rely on the format string for typing.
    – Lev M.
    yesterday






  • 1




    @chux Missed that. Thanks.
    – PSkocik
    yesterday










  • As coded, printing any 'f' returns right after printing (drop through) . Curious: why #define X(Char,Tp) break;case Char: printf(format,((Tp*)vec)[i]) and not #define X(Char,Tp) case Char: printf(format,((Tp*)vec)[i]); break ?
    – chux
    yesterday












  • @chux It's just how I write my switches if they contain mostly "breaking-cases". It doesn't matter with the macro, but in normal C code, if I see each case preceded by break; it'll make one that isn't stand out more easily than if the break were at the end of what follows the case. It helps me quickly catch accidental fall-through. I think it's pretty neat that the C grammar allows me to symmetrically start even the first case with break even though the break part is basically dead code there.
    – PSkocik
    yesterday










  • Hmmm, If you value break at the beginning, perhaps then #define X(Char,Tp) break;case Char: printf(format,((Tp*)vec)[i]); break to avoid the earlier coding oops that caused a "accidental fall-through".
    – chux
    yesterday















up vote
4
down vote



accepted







up vote
4
down vote



accepted






You don't need the dime_se param. The size is more or less implicit in the format character.
Also, if you cast to the right pointer type you can let C do the scaling instead of doing it
manually:



#include <stddef.h>
#include <stdio.h>
void print_vec(void const*vec,size_t dime,char const*format)
{
for(size_t i=0;i<dime;i++)
switch(format[1]){
#define X(Char,Tp) break;case Char: printf(format,((Tp*)vec)[i])
X('c',char);
X('d',unsigned);
X('s',char*);
X('i',int);
X('f',float);
break;default: return;
#undef X
}
}


I said more or less because type promotion kind of blurs the line. %f could well mean you've got a double instead of a float.



If you want to use a dime_se parameter to disambiguate that case, you can:



         break;case 'f': 
if(sizeof(double)==dime_se)
printf(format,((double*)vec)[i]);
else {
assert(sizeof(float)==dime_se);
printf(format,((float*)vec)[i]);
}


but I'm not sure if a print_vec function like that is a good idea.






share|improve this answer














You don't need the dime_se param. The size is more or less implicit in the format character.
Also, if you cast to the right pointer type you can let C do the scaling instead of doing it
manually:



#include <stddef.h>
#include <stdio.h>
void print_vec(void const*vec,size_t dime,char const*format)
{
for(size_t i=0;i<dime;i++)
switch(format[1]){
#define X(Char,Tp) break;case Char: printf(format,((Tp*)vec)[i])
X('c',char);
X('d',unsigned);
X('s',char*);
X('i',int);
X('f',float);
break;default: return;
#undef X
}
}


I said more or less because type promotion kind of blurs the line. %f could well mean you've got a double instead of a float.



If you want to use a dime_se parameter to disambiguate that case, you can:



         break;case 'f': 
if(sizeof(double)==dime_se)
printf(format,((double*)vec)[i]);
else {
assert(sizeof(float)==dime_se);
printf(format,((float*)vec)[i]);
}


but I'm not sure if a print_vec function like that is a good idea.







share|improve this answer














share|improve this answer



share|improve this answer








edited yesterday

























answered yesterday









PSkocik

30.1k54267




30.1k54267












  • Note this answer will only work if your format string always start with a simple type like %d. If you want the function to do fancier printing like fixed number of decimals "%.02f", or print an entire message for each item in the vector, you would need a more complex parsing logic to rely on the format string for typing.
    – Lev M.
    yesterday






  • 1




    @chux Missed that. Thanks.
    – PSkocik
    yesterday










  • As coded, printing any 'f' returns right after printing (drop through) . Curious: why #define X(Char,Tp) break;case Char: printf(format,((Tp*)vec)[i]) and not #define X(Char,Tp) case Char: printf(format,((Tp*)vec)[i]); break ?
    – chux
    yesterday












  • @chux It's just how I write my switches if they contain mostly "breaking-cases". It doesn't matter with the macro, but in normal C code, if I see each case preceded by break; it'll make one that isn't stand out more easily than if the break were at the end of what follows the case. It helps me quickly catch accidental fall-through. I think it's pretty neat that the C grammar allows me to symmetrically start even the first case with break even though the break part is basically dead code there.
    – PSkocik
    yesterday










  • Hmmm, If you value break at the beginning, perhaps then #define X(Char,Tp) break;case Char: printf(format,((Tp*)vec)[i]); break to avoid the earlier coding oops that caused a "accidental fall-through".
    – chux
    yesterday




















  • Note this answer will only work if your format string always start with a simple type like %d. If you want the function to do fancier printing like fixed number of decimals "%.02f", or print an entire message for each item in the vector, you would need a more complex parsing logic to rely on the format string for typing.
    – Lev M.
    yesterday






  • 1




    @chux Missed that. Thanks.
    – PSkocik
    yesterday










  • As coded, printing any 'f' returns right after printing (drop through) . Curious: why #define X(Char,Tp) break;case Char: printf(format,((Tp*)vec)[i]) and not #define X(Char,Tp) case Char: printf(format,((Tp*)vec)[i]); break ?
    – chux
    yesterday












  • @chux It's just how I write my switches if they contain mostly "breaking-cases". It doesn't matter with the macro, but in normal C code, if I see each case preceded by break; it'll make one that isn't stand out more easily than if the break were at the end of what follows the case. It helps me quickly catch accidental fall-through. I think it's pretty neat that the C grammar allows me to symmetrically start even the first case with break even though the break part is basically dead code there.
    – PSkocik
    yesterday










  • Hmmm, If you value break at the beginning, perhaps then #define X(Char,Tp) break;case Char: printf(format,((Tp*)vec)[i]); break to avoid the earlier coding oops that caused a "accidental fall-through".
    – chux
    yesterday


















Note this answer will only work if your format string always start with a simple type like %d. If you want the function to do fancier printing like fixed number of decimals "%.02f", or print an entire message for each item in the vector, you would need a more complex parsing logic to rely on the format string for typing.
– Lev M.
yesterday




Note this answer will only work if your format string always start with a simple type like %d. If you want the function to do fancier printing like fixed number of decimals "%.02f", or print an entire message for each item in the vector, you would need a more complex parsing logic to rely on the format string for typing.
– Lev M.
yesterday




1




1




@chux Missed that. Thanks.
– PSkocik
yesterday




@chux Missed that. Thanks.
– PSkocik
yesterday












As coded, printing any 'f' returns right after printing (drop through) . Curious: why #define X(Char,Tp) break;case Char: printf(format,((Tp*)vec)[i]) and not #define X(Char,Tp) case Char: printf(format,((Tp*)vec)[i]); break ?
– chux
yesterday






As coded, printing any 'f' returns right after printing (drop through) . Curious: why #define X(Char,Tp) break;case Char: printf(format,((Tp*)vec)[i]) and not #define X(Char,Tp) case Char: printf(format,((Tp*)vec)[i]); break ?
– chux
yesterday














@chux It's just how I write my switches if they contain mostly "breaking-cases". It doesn't matter with the macro, but in normal C code, if I see each case preceded by break; it'll make one that isn't stand out more easily than if the break were at the end of what follows the case. It helps me quickly catch accidental fall-through. I think it's pretty neat that the C grammar allows me to symmetrically start even the first case with break even though the break part is basically dead code there.
– PSkocik
yesterday




@chux It's just how I write my switches if they contain mostly "breaking-cases". It doesn't matter with the macro, but in normal C code, if I see each case preceded by break; it'll make one that isn't stand out more easily than if the break were at the end of what follows the case. It helps me quickly catch accidental fall-through. I think it's pretty neat that the C grammar allows me to symmetrically start even the first case with break even though the break part is basically dead code there.
– PSkocik
yesterday












Hmmm, If you value break at the beginning, perhaps then #define X(Char,Tp) break;case Char: printf(format,((Tp*)vec)[i]); break to avoid the earlier coding oops that caused a "accidental fall-through".
– chux
yesterday






Hmmm, If you value break at the beginning, perhaps then #define X(Char,Tp) break;case Char: printf(format,((Tp*)vec)[i]); break to avoid the earlier coding oops that caused a "accidental fall-through".
– chux
yesterday




















 

draft saved


draft discarded



















































 


draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53237886%2fc-print-a-generic-type-vector%23new-answer', 'question_page');
}
);

Post as a guest




















































































Popular posts from this blog

Full-time equivalent

Bicuculline

さくらももこ