![](/img/trans.png)
[英]How can i increase a value of an variable passed as an argument to a function in C
[英]How can a function change the original variable, when it is passed as value argument to the function?
我有以下代码片段:
static const unsigned MAX_DIR_ITEMS = 4;
void fetchAlbum(int sd, const unsigned volref, const char *root, const char *name) {
int dirItems = MAX_DIR_ITEMS;
VFSDirInfo dirInfo[MAX_DIR_ITEMS];
FileRef dirRef;
if (dlp_VFSFileOpen(sd, volref, srcAlbumDir, vfsModeRead, &dirRef) < 0) {
jp_logf(L_GUI, "Could not open dir '%s' on volume %d\n", srcAlbumDir, volref);
return;
}
enum dlpVFSFileIteratorConstants itr = vfsIteratorStart;
while (itr != vfsIteratorStop) {
PI_ERR bytes;
itr = vfsIteratorStart;
jp_logf(L_DEBUG, "Enumerate dir '%s', dirRef=%d, itr=%d, dirItems=%d\n", srcAlbumDir, dirRef, (int)itr, dirItems);
if ((bytes = dlp_VFSDirEntryEnumerate(sd, dirRef, (unsigned long *)&itr, &dirItems, dirInfo)) < 0) {
jp_logf(L_FATAL, "Enumerate ERROR: bytes=%d, dirRef=%d, itr=%d, dirItems=%d\n", bytes, dirRef, (int)itr, dirItems);
break;
} else {
jp_logf(L_DEBUG, "Enumerate OK: bytes=%d, dirRef=%d, itr=%d, dirItems=%d\n", bytes, dirRef, (int)itr, dirItems);
}
使用的函数定义为:
/** @file pi-args.h
* @brief Macros for prototype definitions
*
*/
#if ((defined(__STDC__) || defined(SABER)) && !defined(NO_PROTOTYPE)) || defined(__cplusplus) || defined(USE_PROTOTYPE) || defined(CAN_PROTOTYPE)
# define PI_ARGS(x) x
# define PI_CONST const
#else
# define PI_ARGS(x) ()
# define PI_CONST
#endif
typedef unsigned long FileRef; /**< Type for file references when working with VFS files and directories. */
/** @name Expansion manager and VFS manager constants */
/*@{*/
/** @brief VFS file iterator constants */
enum dlpVFSFileIteratorConstants {
vfsIteratorStart = 0, /** < Indicates that iterator is beginning */
vfsIteratorStop = -1 /**< Indicate that iterator has gone through all items */
};
/*@}*/
/** @name Expansion manager functions */
/*@{*/
/** @brief Iterate through the entries in a directory
*
* Supported on Palm OS 4.0 and later. At the beginning you set
* @p dirIterator to #vfsIteratorStart, then call this function
* repeatedly until it returns an error code of the iterator becomes
* #vfsIteratorStop.
*
* @bug On some early OS 5 devices like Tungsten T and Sony NX70, NX73 this
* call crashes the device. This has been confirmed to be a bug in HotSync on
* the device, as tests showed that a regular HotSync conduit does crash the
* device with this call too.
*
* @param sd Socket number
* @param dirref Directory reference obtained from dlp_VFSFileOpen()
* @param diriterator Ptr to an iterator. Start with #vfsIteratorStart
* @param maxitems On input, the max number of VFSDirInfo structures stored in @p dirItems. On output, the actual number of items.
* @param diritems Preallocated array that contains a number of VFSDirInfo structures on return.
* @return A negative value if an error occured (see pi-error.h)
*/
extern PI_ERR dlp_VFSDirEntryEnumerate
PI_ARGS((int sd, FileRef dirref, unsigned long *diriterator,
int *maxitems, struct VFSDirInfo *diritems));
/*@}*/
使用此代码,我得到以下令人惊讶的 output。 所以我想知道,变量dirRef
如何改变它的值。
Enumerate dir '/Photos & Videos', dirRef=445317240, itr=0, dirItems=4
Enumerate OK: bytes=170, dirRef=0, itr=-1, dirItems=4
我使用的库来自这里: https://github.com/desrod/pilot-link
按值传递变量不提供在 function 内更改它的方法。
int foo(int x)
{
x = x *2;
return x;
}
变量x
是自动局部变量,如果您在 function 中更改它,它不会影响按值传递给 function 的 object。
例子:
int main(void)
{
int y = 4;
foo(y);
printf("%d\n", y);
}
Output: 4
。
您可以确定传递给此 function 的变量不会因为 function 内部参数的更改而改变。 它由 C 标准保证。
宏 PI_ARGS 是否有可能以不可见的方式改变某些东西?
不,您可以通过浏览您发布的 git 存储库自行轻松检查:
#if ((defined(__STDC__) || defined(SABER)) && !defined(NO_PROTOTYPE)) || defined(__cplusplus) || defined(USE_PROTOTYPE) || defined(CAN_PROTOTYPE)
# define PI_ARGS(x) x
# define PI_CONST const
#else
# define PI_ARGS(x) ()
# define PI_CONST
#endif
PS 有时人们会被宏之类的函数弄糊涂。
#define X2(x) ((x) = (x) * 2)
int main(void)
{
int y = 5;
X2(y);
printf("%d\n", y);
}
我已经通过以下代码找到了问题的原因。
看来, unsigned long
在我的机器上有 64 位。 我一直认为,对于 64 位变量,我需要unsigned long long
。 因此,当 function dlp_VFSDirEntryEnumerate()
返回时, itr
将作为故障写回 64 位值,并且变量dirItems
被部分覆盖。 唯一的谜团是, dirItems
变为0
而不是ffffffff
。
static const unsigned MIN_DIR_ITEMS = 16;
static const unsigned MAX_DIR_ITEMS = 1024;
void fetchAlbum(int sd, const unsigned volref, const char *root, const char *name) {
int dirItems = MIN_DIR_ITEMS;
VFSDirInfo dirInfos[MAX_DIR_ITEMS];
char srcAlbumDir[strlen(root) + (name ? strlen(name) : 0) + 2];
FileRef dirRef;
printf("[GUI] Fetching album '%s' on volume %d\n", name, volref);
strcpy(srcAlbumDir, root); // Album is in /<root>/<name>.
// Unfiled album is really just root dir.
if (name) {
strcat(strcat(srcAlbumDir, "/"), name);
}
if (dlp_VFSFileOpen(sd, volref, srcAlbumDir, vfsModeRead, &dirRef) < 0) {
return;
}
// Iterate over all the files in the album dir, looking for jpegs and 3gp's and 3g2's (videos).
enum dlpVFSFileIteratorConstants itr = vfsIteratorStart;
printf("[DEBUG] &dirItems='%p', sizeof(dirItems)=%lu\n", &dirItems, sizeof(dirItems));
printf("[DEBUG] &dirRef= '%p', sizeof(dirRef)=%lu\n", &dirRef, sizeof(dirRef));
printf("[DEBUG] &itr= '%p', sizeof(itr)=%lu\n", &itr, sizeof(itr));
printf("[DEBUG] sizeof(int)=%lu\n", sizeof(int));
printf("[DEBUG] sizeof(long)=%lu\n", sizeof(long));
printf("[DEBUG] sizeof(unsigned)=%lu\n", sizeof(unsigned));
printf("[DEBUG] sizeof(unsigned long)=%lu\n", sizeof(unsigned long));
printf("[DEBUG] sizeof(unsigned long long)=%lu\n", sizeof(unsigned long long));
for (int dirItems_backup; (dirItems_backup = dirItems) <= MAX_DIR_ITEMS; dirItems *= 2) {
PI_ERR bytes;
itr = vfsIteratorStart;
FileRef dirRef_backup = dirRef; // Unfortunately the following call deletes the original value
printf("[DEBUG] Enumerate album '%s', dirRef=%llx, itr=%llx, dirItems=%d\n", srcAlbumDir, dirRef, (long long int)itr, dirItems);
if ((bytes = dlp_VFSDirEntryEnumerate(sd, dirRef, (unsigned long *)&itr, &dirItems, dirInfos)) < 0) {
printf("[FATAL] Enumerate ERROR: bytes=%d, dirRef=%llx, itr=%llx, dirItems=%d\n", bytes, dirRef, (long long int)itr, dirItems);
break;
}
printf("[DEBUG] Enumerate OK: bytes=%d, dirRef=%llx, itr=%llx, dirItems=%d\n", bytes, dirRef, (long long int)itr, dirItems);
dirRef = dirRef_backup;
printf("[DEBUG] Rescued from backup: dirRef=%llx\n", dirRef);
if (dirItems < dirItems_backup) {
break;
}
}
dlp_VFSFileClose(sd, dirRef);
[.....] // process files from the retrieved dirInfos
return;
}
这是我得到的 output:
[GUI] Fetching album '(null)' on volume 1
[DEBUG] &dirItems='0x7ffee6335848', sizeof(dirItems)=4
[DEBUG] &dirRef= '0x7ffee6335850', sizeof(dirRef)=8
[DEBUG] &itr= '0x7ffee633584c', sizeof(itr)=4
[DEBUG] sizeof(int)=4
[DEBUG] sizeof(long)=8
[DEBUG] sizeof(unsigned)=4
[DEBUG] sizeof(unsigned long)=8
[DEBUG] sizeof(unsigned long long)=8
[DEBUG] Enumerate album '/Photos & Videos', dirRef=20a70070, itr=0, dirItems=16
[DEBUG] Enumerate OK: bytes=170, dirRef=0, itr=ffffffffffffffff, dirItems=8
[DEBUG] Rescued from backup: dirRef=20a70070
所以现在正确的代码是:
unsigned long itr;
[.....]
itr = (unsigned long)vfsIteratorStart;
if ((bytes = dlp_VFSDirEntryEnumerate(sd, dirRef, &itr, &dirItems, dirInfos)) < 0) {
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.