I have two C functions f1 and f2 that take the same arguments. Based on a condition, I need to invoke one or the other one with the same arguments:
if (condition) {
result = f1(a, b, c);
} else {
result = f2(a, b, c);
}
I understand it is possible to use the syntax:
result = condition ? f1(a, b, c) : f2(a, b, c)
Is it be possible to have a DRY syntax that requires to write arguments a single time?
Yes, it works fine just like you suggested.
The function call operator () just needs a left-hand-side that evaluates to a function pointer, which names of functions do.
There's no need to derefence function pointers when calling, the () operator does that.
This sample program demonstrates:
#include <stdio.h>
static int foo(int x) {
return x + 1;
}
static int bar(int x) {
return x - 1;
}
int main(void) {
for (int i = 0; i < 10; ++i)
printf("%d -> %d\n", i, (i & 1 ? foo : bar)(i));
return 0;
}
It prints:
0 -> -1
1 -> 2
2 -> 1
3 -> 4
4 -> 3
5 -> 6
6 -> 5
7 -> 8
8 -> 7
9 -> 10
There is nothing strange here.
And since C predates Python by a fair bit, perhaps it's Python's semantics that are C-ish here. Or just plain sane, of course. :)
It is possible to use a function pointer like this:
int (*f)(int, int, int, ...);
f = condition ? f1 : f2;
result = (*f)(a, b, c, ...);
Related
Consider the following code i managed to write:
#include <stdio.h>
#define FOR(A, B, C) for(A; B; C++)
int main()
{
FOR(i=0, i<10, i)
printf("%i", i);
return 1;
}
The output is:
0123456789
If i do FOR(i=5, i<10, i)
then respectively the output is 56789
My questions are is that legal? Will it cause any errors in different cases? Does it works exactly like a for loop?
Yes it's a "legal" macro, but no, it does not work like a real for loop.
Your macro won't handle this:
int a, b;
for(a = 0, b = 4711; a < b; ++a);
for instance, since you can't distinguish the , used to build a longer initializing expression to the one used to separate the expressions that make up the parts:
FOR(a = 0, b = 0, a < b, ++a);
will break, since it looks like a call with 4 arguments instead of 3.
A macro is just copied everywhere the preprocessor sees you using the macro keyword. It just copies the text, nothing more.
To elaborate on that a bit more, consider this example:
#define MY_MACRO a
int MY_MACRO = 5;
When the preprocessor comes along it will take the above and change it to:
int a = 5;
and then the compiler will come along and compile it like normal C/C++ code.
When you add arguments to your macro, they are just substituted in place within your macro. This can be a problem, consider the following two macros:
#define BAD_MACRO(a, b) a*b
#define GOOD_MACRO(a, b) (a)*(b)
They look almost the same, but consider the following:
int k = BAD_MACRO(2, 3); // k = 2*3 = 6
int j = GOOD_MACRO(2, 3); // j = 2*3 = 6
int m = BAD_MACRO(2+1, 3); // m = 2+1*3 = 5
int n = GOOD_MACRO(2+1, 3); // n = (2+1)*3 = 9
Although note that neither of these macros are good or bad, they just don't have the same behaviour as a typical function.
This C program is just 143 characters long!
But it “decompresses” into the first 10,000 digits of Pi.
// Created by cheeseMan on 30/11/13.
long a[35014],b,c=35014,d,e,f=1e4,g,h;
int main(int argc, const char * argv[])
{
for(;(b=c-=14);
h=printf("%04ld",e+d/f))
for(e=d%=f;(g=--b*2);d/=g)
d=d*b+f*(h?a[b]:f/5), a[b]=d%--g;
}
I was doing some research on loss-less compression algorithms, still no luck yet, when I came across this pitiny.c.
The weird thing is that it compiles successfully no errors or bugs, but like i said i cannot make heads or tales of the code, even its syntax. I just would like to know whats going on? what is it doing exactly?
Update
This program is a purposely obfuscated implementation of a spigot algorithm for the Digits of Pi from the book Pi - Unleashed and we can find the original version on page 37 of the book which is as follows:
a[52514],b,c=52514,d,e,f=1e4,g,h;main(){for(;b=c-=14;h=printf("%04d",
e+d/f))for(e=d%=f;g=--b*2;d/=g)d=db+f(h?a[b]:f/5),a[b]=d%--g;}
the paper Unbounded Spigot Algorithms for the Digits of Pi does a good job in explaining the algorithm. Basically it is an implementation of this expansion:
Original
The reason it was designed this way other than to make the code impossible to comprehend and impress people escapes me but we can break down what is going on, first here:
long a[35014],b,c=35014,d,e,f=1e4,g,h;
the variables are static since they are global so all variables not explicitly initialized will be initialized to 0. Next we have an outer for loop:
for(;(b=c-=14); h=printf("%04ld",e+d/f)
^ ^ ^
1 2 3
Is an empty initialization and it also a null statement.
Is subtracting 14 from c and assigning the value back to c and also assigning the same value to b. This loop will execute 2500 times since 35014/14 is 2501 and on the 2501th iteration the result will 0 and thus false and the loop will stop.
h is being assigned the result of printf which is the number of characters printed. What is being printed out is the result of e+d/f and always at least 4 digits and zero padded due to 04 in the format specifier.
Now we have an inner for loop:
for(e=d%=f;(g=--b*2);d/=g)
^ ^ ^
1 2 3
Initializes e and d to d modulus f.
Due to operator precedence does a pre-decrement of b and multiples that by 2 and assigns the result to g
d is being divided by g and assigned the result.
Finally the body of the inner for loop:
d=d*b+f*(h?a[b]:f/5), a[b]=d%--g;
^ ^
1 2
uses both the conditional operator in 1 and comma operator in 2. So we could at least split this into:
d = d*b+f*(h?a[b]:f/5) ; // (1)
a[b] = d%--g; // (2)
(1) can further be broken down into:
long tmp = h ? a[b] : f/5 ; // conditional operator
d = (d * b) + f * tmp;
The conditional operator only matters during the first iteration since h is intialized to 0 but will never be 0 again afterwards since it is always assigned a non-zero value in the outer for loop, so other then the first time h will be assigned a[b].
(2) will again due to precedence pre-decrement g first and then evaluate d modulus the result and assign that to a[b].
It can be written as
long a[35014];
long b;
long c=35014;
long d;
long e;
long f=1e4;
long g;
long h;
int main(int argc, const char * argv[])
{
for(; (b=c-=14); h=printf("%04ld",e+d/f)) {
for(e=d%=f; (g=--b*2); d/=g) {
d = (d * b) + f * ( h ? a[b] : f/5);
a[b] = d % --g;
}
}
}
In other words it's double for loop
Just for grins:
"Calculate" Pi to 10,000 digits
Here is a "simplified" version. "Simplified" meaning breaking up the multiple operators, using the results of assignment statements and for loops. Missing are meaningful names.
(this was verified against the results of the original code.
void simplier() {
long a[35014];
long b = 0;
long c = 35000;
long d = 0;
long e = 0;
long f = 10000;
long g = 0;
long h = 0;
long i = 0;
while (c) {
d %= f;
e = d;
b = c-1;
g = b*2;
while(g) {
g -= 1;
i = h ? a[b] : f/5;
d = (d*b) + (f*i);
a[b] = d % g;
d /= g;
b -= 1;
g = b*2;
}
printf("%04ld", e+d/f);
h = 1;
c -= 14;
}
}
Runtimes:
Original time: 1.110
Simplier time: 1.138
Of course most of the time is in the formatting and printing.
Output:
3141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117067982148086513282306647093844609550582231725359408128481117450284102701938521105559644622948954930381964428810975665933446128475648233786783165271201909145648566923460348610454326648213393607260249141273724587006606315588174881520920962829254091715364367892590360011330530548820466521384146951941511609433057270365759591953092186117381932611793105118548074462379962749567351885752724891227938183011949129833673362440656643086021394946395224737190702179860943702770539217176293176752384674818467669405132000568127145263560827785771342757789609173637178721468440901224953430146549585371050792279689258923542019956112129021960864034418159813629774771309960518707211349999998372978049951059731732816096318595024459455346908302642522308253344685035261931188171010003137838752886587533208381420617177669147303598253490428755468731159562863882353787593751957781857780532171226806613001927876611195909216420198938095257201065485863278865936153381827968230301952035301852968995773622599413891249721775283479131515574857242454150695950829533116861727855889075098381754637464939319255060400927701671139009848824012858361603563707660104710181942955596198946767837449448255379774726847104047534646208046684259069491293313677028989152104752162056966024058038150193511253382430035587640247496473263914199272604269922796782354781636009341721641219924586315030286182974555706749838505494588586926995690927210797509302955321165344987202755960236480665499119881834797753566369807426542527862551818417574672890977772793800081647060016145249192173217214772350141441973568548161361157352552133475741849468438523323907394143334547762416862518983569485562099219222184272550254256887671790494601653466804988627232791786085784383827967976681454100953883786360950680064225125205117392984896084128488626945604241965285022210661186306744278622039194945047123713786960956364371917287467764657573962413890865832645995813390478027590099465764078951269468398352595709825822620522489407726719478268482601476990902640136394437455305068203496252451749399651431429809190659250937221696461515709858387410597885959772975498930161753928468138268683868942774155991855925245953959431049972524680845987273644695848653836736222626099124608051243884390451244136549762780797715691435997700129616089441694868555848406353422072225828488648158456028506016842739452267467678895252138522549954666727823986456596116354886230577456498035593634568174324112515076069479451096596094025228879710893145669136867228748940560101503308617928680920874760917824938589009714909675985261365549781893129784821682998948722658804857564014270477555132379641451523746234364542858444795265867821051141354735739523113427166102135969536231442952484937187110145765403590279934403742007310578539062198387447808478489683321445713868751943506430218453191048481005370614680674919278191197939952061419663428754440643745123718192179998391015919561814675142691239748940907186494231961567945208095146550225231603881930142093762137855956638937787083039069792077346722182562599661501421503068038447734549202605414665925201497442850732518666002132434088190710486331734649651453905796268561005508106658796998163574736384052571459102897064140110971206280439039759515677157700420337869936007230558763176359421873125147120532928191826186125867321579198414848829164470609575270695722091756711672291098169091528017350671274858322287183520935396572512108357915136988209144421006751033467110314126711136990865851639831501970165151168517143765761835155650884909989859982387345528331635507647918535893226185489632132933089857064204675259070915481416549859461637180270981994309924488957571282890592323326097299712084433573265489382391193259746366730583604142813883032038249037589852437441702913276561809377344403070746921120191302033038019762110110044929321516084244485963766983895228684783123552658213144957685726243344189303968642624341077322697802807318915441101044682325271620105265227211166039666557309254711055785376346682065310989652691862056476931257058635662018558100729360659876486117910453348850346113657686753249441668039626579787718556084552965412665408530614344431858676975145661406800700237877659134401712749470420562230538994561314071127000407854733269939081454664645880797270826683063432858785698305235808933065757406795457163775254202114955761581400250126228594130216471550979259230990796547376125517656751357517829666454779174501129961489030463994713296210734043751895735961458901938971311179042978285647503203198691514028708085990480109412147221317947647772622414254854540332157185306142288137585043063321751829798662237172159160771669254748738986654949450114654062843366393790039769265672146385306736096571209180763832716641627488880078692560290228472104031721186082041900042296617119637792133757511495950156604963186294726547364252308177036751590673502350728354056704038674351362222477158915049530984448933309634087807693259939780541934144737744184263129860809988868741326047215695162396586457302163159819319516735381297416772947867242292465436680098067692823828068996400482435403701416314965897940924323789690706977942236250822168895738379862300159377647165122893578601588161755782973523344604281512627203734314653197777416031990665541876397929334419521541341899485444734567383162499341913181480927777103863877343177207545654532207770921201905166096280490926360197598828161332316663652861932668633606273567630354477628035045077723554710585954870279081435624014517180624643626794561275318134078330336254232783944975382437205835311477119926063813346776879695970309833913077109870408591337464144282277263465947047458784778720192771528073176790770715721344473060570073349243693113835049316312840425121925651798069411352801314701304781643788518529092854520116583934196562134914341595625865865570552690496520985803385072242648293972858478316305777756068887644624824685792603953527734803048029005876075825104747091643961362676044925627420420832085661190625454337213153595845068772460290161876679524061634252257719542916299193064553779914037340432875262888963995879475729174642635745525407909145135711136941091193932519107602082520261879853188770584297259167781314969900901921169717372784768472686084900337702424291651300500516832336435038951702989392233451722013812806965011784408745196012122859937162313017114448464090389064495444006198690754851602632750529834918740786680881833851022833450850486082503930213321971551843063545500766828294930413776552793975175461395398468339363830474611996653858153842056853386218672523340283087112328278921250771262946322956398989893582116745627010218356462201349671518819097303811980049734072396103685406643193950979019069963955245300545058068550195673022921913933918568034490398205955100226353536192041994745538593810234395544959778377902374216172711172364343543947822181852862408514006660443325888569867054315470696574745855033232334210730154594051655379068662733379958511562578432298827372319898757141595781119635833005940873068121602876496286744604774649159950549737425626901049037781986835938146574126804925648798556145372347867330390468838343634655379498641927056387293174872332083760112302991136793862708943879936201629515413371424892830722012690147546684765357616477379467520049075715552781965362132392640616013635815590742202020318727760527721900556148425551879253034351398442532234157623361064250639049750086562710953591946589751413103482276930624743536325691607815478181152843667957061108615331504452127473924544945423682886061340841486377670096120715124914043027253860764823634143346235189757664521641376796903149501910857598442391986291642193994907236234646844117394032659184044378051333894525742399508296591228508555821572503107125701266830240292952522011872676756220415420516184163484756516999811614101002996078386909291603028840026910414079288621507842451670908700069928212066041837180653556725253256753286129104248776182582976515795984703562226293486003415872298053498965022629174878820273420922224533985626476691490556284250391275771028402799806636582548892648802545661017296702664076559042909945681506526530537182941270336931378517860904070866711496558343434769338578171138645587367812301458768712660348913909562009939361031029161615288138437909904231747336394804575931493140529763475748119356709110137751721008031559024853090669203767192203322909433467685142214477379393751703443661991040337511173547191855046449026365512816228824462575916333039107225383742182140883508657391771509682887478265699599574490661758344137522397096834080053559849175417381883999446974867626551658276584835884531427756879002909517028352971634456212964043523117600665101241200659755851276178583829204197484423608007193045761893234922927965019875187212726750798125547095890455635792122103334669749923563025494780249011419521238281530911407907386025152274299581807247162591668545133312394804947079119153267343028244186041426363954800044800267049624820179289647669758318327131425170296923488962766844032326092752496035799646925650493681836090032380929345958897069536534940603402166544375589004563288225054525564056448246515187547119621844396582533754388569094113031509526179378002974120766514793942590298969594699556576121865619673378623625612521632086286922210327488921865436480229678070576561514463204692790682120738837781423356282360896320806822246801224826117718589638140918390367367222088832151375560037279839400415297002878307667094447456013455641725437090697939612257142989467154357846878861444581231459357198492252847160504922124247014121478057345510500801908699603302763478708108175450119307141223390866393833952942578690507643100638351983438934159613185434754649556978103829309716465143840700707360411237359984345225161050702705623526601276484830840761183013052793205427462865403603674532865105706587488225698157936789766974220575059683440869735020141020672358502007245225632651341055924019027421624843914035998953539459094407046912091409387001264560016237428802109276457931065792295524988727584610126483699989225695968815920560010165525637567
This question already has answers here:
C macros and use of arguments in parentheses
(2 answers)
Closed 4 years ago.
I am new to c language. I just wanted to know why is my macro not working properly. It is giving me output as 13 where as my expected output is 24.?
#include<stdio.h>
#define mult(a,b) a*b
int main()
{
int x=4,y=5;
printf("%d",mult(x+2,y-1));
return 0;
}
mult(x+2,y-1) expands to x +2 * y -1 that is equals to 4 + 2 * 5 -1 gives output: 13.
You might be expecting answer (4 + 2) * (5 -1) = 6 * 4 = 24. To make it expand like this you should write parenthesize macro as #H2Co3 also suggesting:
#define mult(a,b) ((a)*(b))
Read aslo: So, what's wrong with using macros? by Bjarne Stroustrup.
This is because C macros are simple textual substitutions, the macro writer must be sure to insert parentheses around every macro variable when it is substituted, and around the macro expansion itself, to prevent the resulting expansion from taking on new meanings.
If you observe your program: mult(a, b) is defined as a * b
mult(x + 2, y - 1) = x + 2 * y - 1 = 4 + 2 * 5 - 1 = 4 + 10 - 1 = 13
The Correct way would be:
mult(a, b) ((a) * (b))
Use parentheses in the macro definition
#include<stdio.h>
#define mult(a,b) ((a)*(b))
int main()
{
int x=4,y=5;
printf("%d",mult(x+2,y-1));
return 0;
}
This is because different arithmetic operators have different precedence levels. Hence always use parentheses while defining the macro.
Because it replaces the arguments literally:
mult(x+2,y-1) --> mult(4+2,5-1) --> 4 + 2*5 - 1 --> 13
Try changing the define to:
#define mult(a,b) (a)*(b)
In this case the result after pre-processing is this:
int main()
{
int x=4,y=5;
printf("%d",(x+2)*(y-1));
return 0;
}
This will solve the problem but it's still not the best way to do it.
#define mult(a,b) ((a)*(b))
This version is considered as good practice because in other types of situation the first one would fail. See the bellow example:
#include<stdio.h>
#define add(a,b) (a)+(b)
int main()
{
int x=4,y=5;
printf("%d",add(x+2,y-1)*add(x+2,y-1));
return 0;
}
In this case it would give an incorrect answer because it is translated by the pre-processor to the fallowing:
int main()
{
int x=4,y=5;
printf("%d",(x+2)+(y-1)*(x+2)+(y-1));
return 0;
}
printing 34 instead of 100.
For the ((a)+(b)) version it would translate to:
int main()
{
int x=4,y=5;
printf("%d",((x+2)+(y-1))*((x+2)+(y-1)));
return 0;
}
giving a correct answer.
This question already has answers here:
Why are these constructs using pre and post-increment undefined behavior?
(14 answers)
Closed 4 years ago.
Possible Duplicate:
Parameter evaluation order before a function calling in C
For the below code I expected the output to be 20 and 76 but instead 75 and 21 is comming as output .Please explain why is so.
#include<stdio.h>
unsigned func(unsigned n)
{
unsigned int a =1 ;
static unsigned int b=2;
a+=b; b+=a;
{
unsigned int a=3;
a+=b; b+=a;
}
//printf("%d %d ",a,b);
return (n+a+b);
}
int main()
{
printf("%d %d\n",func(4),func(5));
return 0;
}
you are expecting func(4) to be called before func(5) but the opposite happens with your compiler. The order of evaluation of function parameters is unspecified by C standard. So, compiler is free choose which function to call first. So across different runs you may observe different order of function calls, though it's very unlikely to happen that way with the same compiler.
The order of evaluation of func(4) and func(5) isn't defined by the C standard(s).
The order of evaluation of expression is unspecified behaviour hence func(4) and func(5) may be called in different order as you supposed to
You might like to visit it for more
Compilers and argument order of evaluation in C++
Parameter evaluation order before a function calling in C
The arguments are pushed onto stack in reverse order. It seems in your compiler implementation, func(5) is called before func(4).
Order of evaluation could be the reason. Because,
//printf("%d %d\n",func(4),func(5));
printf("%d \n",func(4));
printf("%d \n",func(5));
prints
20
76
func(5) is getting executed first :
Values of variables after executing func(5) :
a = 3
b = 13
func(5) = 21
Since, b is static, the values after executing func(4):
a = 14
b = 57
func(4) = 75
The code is simple, and remember static variables will preserve their values between function calls.
In your program, due to your compiler(thus compiler specific, not defined by standards):
func(5) is executed first, : which returns 21..
explanation:
unsigned func(unsigned n) /*first with 5*/
{
unsigned int a =1 ;
static unsigned int b=2;
a+=b; b+=a; // a = 3, b = 5
{
unsigned int a=3;
a+=b; b+=a; // a = 8, b = 13
}
//printf("%d %d ",a,b);
return (n+a+b); // 5 + 3 + 13 = 21.
}
func(4) is executed next,
explanation:
unsigned func(unsigned n) /*first with 5*/
{
unsigned int a =1 ;
static unsigned int b=2;
a+=b; b+=a; // a = 14, b = 27
{
unsigned int a=3;
a+=b; b+=a; // a = 30, b = 57
}
//printf("%d %d ",a,b);
return (n+a+b); // 4 + 57 + 14 = 75(which is printed first).
}
Hence the output.
There is a well known term for this called "function side effects". You change a variable inside a function, call the function and rely upon a statement using the variable expecting it to have already changed. Generally this should be avoided and is not a good approach.
A better alternate in such a scenario is either call function and store the return values and then use them in printf or make two different printf calls.
side effects
Here is the program that I am trying to compile
#include<stdio.h>
int main()
{
int i = 0;
rec(i);
}
int rec(int i)
{
i = i + 1;
if (i == 10){return true;}
rec(i);
printf("i: %d\n", i);
}
I am getting this output
$ gcc -o one one.c
one.c: In function ‘rec’:
one.c:10:24: error: ‘true’ undeclared (first use in this function)
one.c:10:24: note: each undeclared identifier is reported only once for each function it appears in
As far I believe is Boolean true evaluates to 1 in c. If so why am I getting an error?
There are no true or false keywords in C. There are some library definitions for those values in stdbool.h (starting in C99, I think) but oft times most C programmers will just use 1 and 0.
If you don't want to use stdbool.h, or you're working on a compiler that doesn't support it, you can usually define the constants yourself with something like:
#define FALSE (1==0)
#define TRUE (1==1)
or you can use 1 and 0 directly - the method above is for those who don't want to have to remember which integer values apply to which truth values (a).
0 is false, any other value is true. So your code would look something like (fixing up the return value problem as well though I'm not sure why that's even there since it always returns true.):
#include <stdio.h>
int rec (int i) {
i = i + 1;
if (i == 10)
return 1;
printf ("i: %d\n", i);
return rec (i);
}
int main (void) {
int rv, i = 0;
rv = rec (i);
printf ("rv: %d\n", rv);
return 0;
}
which gives you:
i: 1
i: 2
i: 3
i: 4
i: 5
i: 6
i: 7
i: 8
i: 9
rv: 1
I should also mention that recursion is a solution best used when the search space is reduced quickly, such as in a binary tree search where the search spaces halves on each recursive call. It's not usually a good fit for something where you just increment a value on each call although, in this case, it's probably okay since you limit it to about ten levels.
(a): Keep in mind the caveat that, although the given definition of TRUE will most be 1, any non-zero value will be treated so. That means that the two statements:
if (isValid)
if (isValid == TRUE)
do not mean the same thing. There are a large number of possible isValid values which will be pass the first test but fail the second. That's usually not a problem since it's almost always a bad idea to compare boolean variables with boolean constants anyway.
If you want to use true/false, you can put your compiler in C99 mode (std=c99 for GCC) (or C11), and include <stdbool.h>.
(Or you'll need to define true and false using preprocessor directives or global constants.)
You can put a simple 'if' statement in it
#include<stdio.h>
int main()
{
int i = 0;
rec(i);
}
int rec(int i)
{
i = i + 1;
if (i == 10){
return 1;
}
j = rec(i)
if (j == 1){
printf('true')
}
printf("i: %d\n", i);
}
c does not have a boolean proper. You could have a define for it though
#define true 1
#define false 0
If your C doesn't use the C99 standard, then there is neither true nor false. When designing a function that returns a boolean, i.e.
short isOdd(long);
I would use 1 and 0 to represent true and false respectively. This is ok because if you try the following snippet with i=1 (or any non-zero ints), it prints T; with i=0, it prints F.
if (i)
putch('T');
else
putch('F');
Here's the example of an function that tests if a number is odd:
short isOdd(long num)
{
return num%2; // evals to 1 if num is odd; 0 otherwise
}
Hope that helps.