在C函数内部声明函数

时间:2018-07-10 08:46:28

标签: c function function-pointers function-declaration

我在在线考试中发现了这个问题。这是代码:

#include <stdio.h>

int main(void) {
    int demo();
    demo();
    (*demo)();
    return 0;
}

int demo(){
    printf("Morning");
}

测试后我看到了答案。这就是答案:

MorningMorning

我阅读了说明,但不明白为什么会这样。 我的意思是,行int demo();是否应该引起任何 “问题”

任何解释都是有帮助的。谢谢。

4 个答案:

答案 0 :(得分:5)

这不是问题,因为echo date_format($date,"Y/m/d H:i:s"); //e.g. 2013/03/15 00:00:00 echo date_format($date,"dmy"); //e.g. 150313 -- Y capital would return 2013 不是函数定义,它只是一个外部声明,表示(声明)具有该名称的函数。

在C语言中,您无法定义嵌套函数:

JSONArray jsonImage = new JSONArray();

for(int i=0; i<imageList.size(); i++){
    JSONObject imgObj = new JSONObject();
    String imageBitmap = imageList.get(i).getimageBitmap();
    String imageName = imageList.get(i).getImage_name();
    imgObj.put("imageName",imageName);
    imgObj.put("imageBitmap", imageBitmap);

    jsonImage.put(imgObj);
}

LocationManager lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);

if (ActivityCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
    // TODO: Consider calling
}

Location location = lm.getLastKnownLocation(LocationManager.GPS_PROVIDER);
double longitude = location.getLongitude();
double latitude = location.getLatitude();

Calendar calendar = Calendar.getInstance();
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String formattedDate = format.format(calendar.getTime());

final String jsonStringArray = jsonArray.toString();

final String jsonImageString= jsonImage.toString();

URL url = new URL(AppState.DEV_URL + AppState.DEV_API + "storeAnswer");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(10000);
conn.setConnectTimeout(15000);
conn.setRequestMethod("POST");
conn.setDoInput(true);
conn.setDoOutput(true);
conn.setRequestProperty("Content-Type","application/json");
conn.connect();

JSONObject data = new JSONObject();
data.put("token", Uri.encode(UserLocalStore.userLocalStore.getToken()));
data.put("latitude", Uri.encode(String.valueOf(latitude)));
data.put("longitude",Uri.encode(String.valueOf(longitude)));
data.put("answers", Uri.encode(jsonStringArray));
data.put("images", Uri.encode(jsonImageString));
data.put("time", Uri.encode(formattedDate));

OutputStreamWriter out = new   OutputStreamWriter(conn.getOutputStream());
out.write(data.toString());
out.close();

但是您可以声明一个函数就可以了。它实际上等效于:

int demo();

除了在您的代码中,外部转发int main(void) { int demo() {} //Error: nested function!!! } 声明仅在#include <stdio.h> int demo(); //function declaration, not definition int main(void) { demo(); (*demo)(); return 0; } int demo(){ printf("Morning"); } 内部可见。

答案 1 :(得分:4)

您可以在另一个函数中声明一个函数。这是允许的。唯一的事情是它仅在声明它的函数内部可见。

答案 2 :(得分:2)

其他答案未解释

(*demo)();

部分。这是部分解释:

demo(不带括号)是函数 pointer 。因此,您可以首先取消引用它以获得函数然后用括号将其调用(将取消引用的对象包装到括号中,否则意味着您要取消引用该函数的返回值

因此它严格等于

demo();

(当函数指针存储在变量中时,此符号很有用,这里比必要的要隐秘得多)

答案 3 :(得分:0)

int main(void) { int demo(); /*...*/ }; int demo(){ /*...*/ } 相当于 int main(void) { extern int demo(); /*...*/ }; int demo(){ /*...*/ } 它在主函数内部声明具有外部链接的演示函数。 demo标识符将一直有效到作用域的结尾,但是demo将是一个 正常的外部功能。

不幸的是,您无法对static的函数执行此操作,因为 标准(http://port70.net/~nsz/c/c11/n1570.html#note30)使类似 int main(void) { static int demo(); } static int demo(){ /*...*/ } 非法。

关于(*demo)();起作用的原因,并且在这种情况下等效于demo();(&demo)();(*&demo)();

使用int demo();声明演示后,demo是一个函数指示符(它与函数指针不同,与数组指示符不相同是与数组的第一个指针不同)元件)。但是,就像数组一样,函数指定符几乎总是衰减到函数指针(请参阅6.3.2.1p4),并且这种类型的衰减也发生在函数调用中。本质上demo();demo衰减为一个指针,然后调用 函数指针。将*应用于这样的指针会再次产生函数指示符,该函数指示符又会衰减到进行调用的指针。

诚然,所有这些东西都是非常奇怪和深奥的,我什至无法想到区分是有用的情况。恕我直言,最好是坚持使用demo();(demo)()(如果要抑制宏扩展),并且永远不要使用(*demo)()(至少不在函数上-在函数指针上)至少提供了一些信息),尤其是(&demo)(),因为它除了使读者感到困惑之外没有其他用途。