Reputation: 2552
The function I'm working on requires two strings as input (as well as some other parameters) and returns two different strings on output. I thought the most logical way to do this would be to return an int
for the error and have two pointers to C strings as arguments. This is how I do that:
int annealc(const char *sequence1, const char *sequence2, float startTemp, float endTemp, float tempStep, int cycles, char *retVal1, char *retVal2, int *score)
{
...
retVal1 = malloc(MAX(len1, len2));
retVal2 = malloc(MAX(len1, len2));
...
strcpy(retVal1, sequence1);
strcpy(retVal2, sequence2);
...
//Somewhere along the line retVal is exchanged for another string
free(retVal1);
free(retVal2);
retVal1 = currentSeq1;
retVal2 = currentSeq2;
...
*score = bestScore;
return 0;
}
//Intended use:
int error = annealc(content1, content2,
30, 5, 1, 5,
alignment1, alignment2, &score);
I don't think I'm using the syntax for pointers properly, because when the function returns there's no value in either alignment1
or alignment2
. So, what am I doing wrong?
Thanks for your help!
Upvotes: 1
Views: 222
Reputation: 7738
You're correct you're not using the right parameter types. You want the pointers you're setting in the function and expect to have values after returning to be typed as pointer to a pointer.
Something like.
int annealc
(
const char *sequence1,
const char *sequence2,
float startTemp,
float endTemp,
float tempStep,
int cycles,
char **retVal1,
char **retVal2,
int *score
)
{
...
*retVal1 = malloc(MAX(len1, len2));
*retVal2 = malloc(MAX(len1, len2));
...
strcpy(*retVal1, sequence1);
strcpy(*retVal2, sequence2);
...
//Somewhere along the line retVal is exchanged for another string
free(*retVal1);
free(*retVal2);
*retVal1 = currentSeq1;
*retVal2 = currentSeq2;
...
*score = bestScore;
return 0;
}
//Intended use:
int error = annealc(content1, content2,
30, 5, 1, 5,
&alignment1, &alignment2, &score);
The reason is that in your version the parameters retVal1 and retVal2 are just typed only as char pointers. This means those variables just hold an address value that can be dereferenced by using *retVal1 or *retVal2 to examine or modify the character at that address.
When you type them as pointer-to-a-pointer now they hold a reference to an address of some other pointer. Dereferencing the pointer-to-a-pointer allows you to examine or modify the address that the other pointer references.
This is best illustrated by the following example:
#include <stdio.h>
#include <string.h>
#include <memory.h>
void sample1(char *inner)
{
printf("IN SAMPLE1 BEFORE MALLOC: Address of inner is %p\n", &inner);
printf("IN SAMPLE1 BEFORE MALLOC: Address held by inner is %p\n", inner);
printf("IN SAMPLE1 BEFORE MALLOC: The char referenced by inner is %c\n", *inner);
inner = (char *)malloc(4);
strcpy(inner, "WXYZ");
printf("IN SAMPLE1 AFTER MALLOC: Address of inner is %p\n", &inner);
printf("IN SAMPLE1 AFTER MALLOC: Address held by inner is %p\n", inner);
printf("IN SAMPLE1 AFTER MALLOC: The char referenced by inner is %c\n\n", *inner);
}
void sample2(char **inner)
{
printf("IN SAMPLE2 BEFORE MALLOC: Address of inner is %p\n", &inner);
printf("IN SAMPLE2 BEFORE MALLOC: Address of the pointer held by inner is %p\n", inner);
printf("IN SAMPLE2 BEFORE MALLOC: Address of the char referenced by the address held by inner is %p\n", *inner);
printf("IN SAMPLE2 BEFORE MALLOC: The char referenced by the address held by inner is %c\n\n", **inner);
*inner = (char *)malloc(sizeof(char));
**inner = 'W';
printf("IN SAMPLE2 AFTER MALLOC: Address of inner is %p\n", &inner);
printf("IN SAMPLE2 AFTER MALLOC: Address of the pointer held by inner is %p\n", inner);
printf("IN SAMPLE2 AFTER MALLOC: Address of the char referenced by the address held by inner is %p\n", *inner);
printf("IN SAMPLE2 AFTER MALLOC: The char referenced by the address held by inner is %c\n\n", **inner);
}
int main(int argc, char *argv[])
{
char myChar = 'A';
char *outer = &myChar;
printf("Addres of myChar is %p\n\n", &myChar);
printf("BEFORE sample1: Address of outer is %p\t\t\t\t\t\tThis is where the variable 'outer' resides in memory.\n", &outer);
printf("BEFORE sample1: Address of the char held by outer is %p\t\t\t\tThis matches the address of 'myChar' because that is what we set 'outer' to.\n", outer);
printf("BEFORE sample1: The char referenced by the address held by outer is %c\t\t\tThis is the same as the value held by 'myChar'.\n\n", *outer);
sample1(outer);
printf("AFTER sample1: Address of outer is %p\t\t\t\t\t\tThe variable 'outer' is unaffected by the call to sample1.\n", &outer);
printf("AFTER sample1: Address of the char held by outer is %p\n", outer);
printf("AFTER sample1: The char referenced by outer is %c\n\n\n", *outer);
printf("BEFORE sample2: Address of outer is %p\t\t\t\t\t\tThis is all the same as before sample1 since 'outer' was not affected.\n", &outer);
printf("BEFORE sample2: Address of the char held by outer is %p\n", outer);
printf("BEFORE sample2: The char referenced by the address held by outer is %c.\n\n", *outer);
printf("BEFORE sample2: Address of outer is %p\n", &outer);
printf("BEFORE sample2: Address referenced by outer is %p\n", outer);
printf("BEFORE sample2: The char referenced by the address held by outer is %c\n\n", *outer);
sample2(&outer);
printf("AFTER sample2: Address of outer is %p\t\t\t\t\t\tThe variable 'outer' still resides in the same place in memory; this didn't change.\n", &outer);
printf("AFTER sample2: Address referenced by outer is %p\t\t\t\t\tThe address held by 'outer' now matches what was assigned inside the call to sample2.\n", outer);
printf("AFTER sample2: The char referenced by the address held by outer is %c\t\t\t...as well as now references the character 'W' which was stored in the memory allocated inside the call to sample2.\n", *outer);
return 0;
}
/*
Example Output:
Addres of myChar is 002EFD33
BEFORE sample1: Address of outer is 002EFD24 This is where the variable 'outer' resides in memory.
BEFORE sample1: Address of the char held by outer is 002EFD33 This matches the address of 'myChar' because that is what we set 'outer' to.
BEFORE sample1: The char referenced by the address held by outer is A This is the same as the value held by 'myChar'.
IN SAMPLE1 BEFORE MALLOC: Address of inner is 002EFC50
IN SAMPLE1 BEFORE MALLOC: Address held by inner is 002EFD33
IN SAMPLE1 BEFORE MALLOC: The char referenced by inner is A
IN SAMPLE1 AFTER MALLOC: Address of inner is 002EFC50
IN SAMPLE1 AFTER MALLOC: Address held by inner is 0075B0F8
IN SAMPLE1 AFTER MALLOC: The char referenced by inner is W
AFTER sample1: Address of outer is 002EFD24 The variable 'outer' is unaffected by the call to sample1.
AFTER sample1: Address of the char held by outer is 002EFD33
AFTER sample1: The char referenced by outer is A
BEFORE sample2: Address of outer is 002EFD24 This is all the same as before sample1 since 'outer' was not affected.
BEFORE sample2: Address of the char held by outer is 002EFD33
BEFORE sample2: The char referenced by the address held by outer is A.
BEFORE sample2: Address of outer is 002EFD24
BEFORE sample2: Address referenced by outer is 002EFD33
BEFORE sample2: The char referenced by the address held by outer is A
IN SAMPLE2 BEFORE MALLOC: Address of inner is 002EFC50
IN SAMPLE2 BEFORE MALLOC: Address of the pointer held by inner is 002EFD24
IN SAMPLE2 BEFORE MALLOC: Address of the char referenced by the address held by inner is 002EFD33
IN SAMPLE2 BEFORE MALLOC: The char referenced by the address held by inner is A
IN SAMPLE2 AFTER MALLOC: Address of inner is 002EFC50
IN SAMPLE2 AFTER MALLOC: Address of the pointer held by inner is 002EFD24
IN SAMPLE2 AFTER MALLOC: Address of the char referenced by the address held by inner is 0075B128
IN SAMPLE2 AFTER MALLOC: The char referenced by the address held by inner is W
AFTER sample2: Address of outer is 002EFD24 The variable 'outer' still resides in the same place in memory; this didn't change.
AFTER sample2: Address referenced by outer is 0075B128 The address held by 'outer' now matches what was assigned inside the call to sample2.
AFTER sample2: The char referenced by the address held by outer is W ...as well as now references the character 'W' which was stored in the memory allocated inside the call to sample2.
*/
Upvotes: 3